Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait for request of CancellationToken cancellation

How can I pause the executing until the cancellation is requested?

var cts = new CancellationTokenSource();

Task.Run(() =>
{
    // Wait for the Cancel...

    Console.WriteLine("Canceled!");
});

Console.ReadKey();

cts.Cancel();

Console.ReadKey();
like image 304
user4388177 Avatar asked Oct 09 '16 10:10

user4388177


People also ask

How do I cancel my CancellationToken?

When given a CancellationToken , you can create a new instance of the token source, assign it's token to the provided token, and cancel it. All other parties that can read this token will see that it's cancellation has been requested.

How do I wait for CancellationToken?

Wait(Int32, CancellationToken) Waits for the Task to complete execution. The wait terminates if a timeout interval elapses or a cancellation token is canceled before the task completes.

How does cancellation token work?

The wait handle of the cancellation token will become signaled in response to a cancellation request, and the method can use the return value of the WaitAny method to determine whether it was the cancellation token that signaled. The operation can then just exit, or throw an OperationCanceledException, as appropriate.

Does disposing a CancellationTokenSource cancel it?

The Dispose method leaves the CancellationTokenSource in an unusable state. After calling Dispose , you must release all references to the CancellationTokenSource so the garbage collector can reclaim the memory that the CancellationTokenSource was occupying.


2 Answers

You can use the WaitHandle to wait synchronously:

static void Main()
{
    var cts = new CancellationTokenSource();

    Task.Run(() =>
    {
        // Wait for the Cancel...

        cts.Token.WaitHandle.WaitOne();

        Console.WriteLine("Canceled!");
    });

    Console.ReadKey();

    cts.Cancel();

    Console.ReadKey();
}

That said, "blocking a thread until something is cancelled" is a very uncommon scenario, so it's possible that you're using the wrong tool for this job. If you need to wait on something (not specifically a cancellation), you can use a TaskCompletionSource instead. If you need to react to a cancellation, you can use CancellationToken.Register to attach a callback (and therefore avoid blocking a thread).

like image 193
Kevin Gosse Avatar answered Oct 23 '22 11:10

Kevin Gosse


The CancellationTokenSource uses a ManualResetEvent internally and you can just wait for the exposed WaitHandle to pause the execution until it is set.

var cts = new CancellationTokenSource();

Task.Run(() =>
{
    WaitHandle.WaitAny(new[] { cts.Token.WaitHandle });

    Console.WriteLine("Canceled!");
});

Console.ReadKey();

cts.Cancel();

Console.ReadKey();

This is the WaitHandle defined in the CancellationTokenSource:

ManualResetEvent mre = new ManualResetEvent(false);
if (Interlocked.CompareExchange(ref m_kernelEvent, mre, null) != null)
{    
    ((IDisposable)mre).Dispose();
}

// There is a ---- between checking IsCancellationRequested and setting the event.
// However, at this point, the kernel object definitely exists and the cases are:
//   1. if IsCancellationRequested = true, then we will call Set()
//   2. if IsCancellationRequested = false, then NotifyCancellation will see that the event exists, and will call Set().
if (IsCancellationRequested)
    m_kernelEvent.Set();

return m_kernelEvent;

And the Token just returns the handle from the source (has an internal variable referencing it).

Another option is to register the Token callback and use your own ManualResetEvent:

var cts = new CancellationTokenSource();

Task.Run(() =>
{
    var mre = new ManualResetEvent(false);

    var registration = cts.Token.Register(() => mre.Set());

    using (registration)
    {
        mre.WaitOne();

        Console.WriteLine("Canceled!");
    }
});

Console.ReadKey();

cts.Cancel();

Console.ReadKey();

Examples: https://blogs.msdn.microsoft.com/pfxteam/2009/05/22/net-4-cancellation-framework/

like image 29
Stefano d'Antonio Avatar answered Oct 23 '22 10:10

Stefano d'Antonio