Cancel a Loop in a Task with CancellationTokens





5.00/5 (2 votes)
Cancel a loop in a task with CancellationTokens
Introduction
In the event that you create an asynchronous Task with a loop, in which you run your code, say you’ve created an asynchronous task. The method you’re running inside your task contains a loop (infinite or not), and you want to break out of it, peacefully. You would need to create a CancellationTokenSource
and pass the Task.Factory.StartNew
method the cancellation Token, also passing the token to the main loop.
A CancellationTokenSource provides a way of signaling its Cancellation Token that it has been cancelled. A CancellationToken notifies the operation that it should be cancelled.
I am creating a new Task using the Factory
property of the Task. I could have created it in a different way, check here for Task Constructors. I am also using the parameters TaskCreationOption.LongRunningTask and TaskScheduler.Default.
TaskCreationOption.LongRunningTask
Specifies that a task will be a long-running, coarse-grained operation involving fewer, larger components than fine-grained systems. It provides a hint to the
TaskScheduler
that oversubscription may be warranted. Oversubscription lets you create more threads than the available number of hardware threads.
TaskScheduler.Default
Gets the default
TaskScheduler
instance that is provided by the .NET Framework.
Here is a simple example on how to achieve this. You can run this code on LinqPad or create a new console project. Just remember to include the System.Threading.Tasks
namespace.
void Main()
{
CancellationTokenSource cts = new CancellationTokenSource();
var token = cts.Token;
Task t = Task.Factory.StartNew(
() => {
MainLoop(token);
},
token,
TaskCreationOptions.LongRunning,
TaskScheduler.Default
);
Console.ReadLine();
cts.Cancel();
try
{
t.Wait();
}
catch( AggregateException ae )
{
// catch inner exception
}
catch( Exception crap )
{
// catch something else
}
}
void MainLoop( CancellationToken token )
{
while( true )
{
// do something here.
Console.Write(".");
Thread.Sleep(100);
// Poll on this property if you have to do
// other cleanup before throwing.
if (token.IsCancellationRequested)
{
// Clean up here, then...
"cleanup".Dump();
token.ThrowIfCancellationRequested();
}
}
}
After creating the Task, it will start automatically. All you have to do is to wait for the result, in this case there won’t be any variable returned, but you have to do this so you can recover if you get an AggregatedException
.
To cancel the Task, just call the method Cancel
from the CancellationTokenSource
. Inside your method, the IsCancellationRequested
property from the token will be true
, giving you time to do some cleanup before throwing the cancellation request.
That’s pretty much it.
Get more information about C# Tasks and the Task Parallelism Library.
I hope you enjoyed this little explanation. Tasks are way much more than this little code snippet, so if you’re interested, check back once in a while, I’ll put up more snippets.