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();
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.
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.
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.
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.
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).
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/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With