C# Task Cancellation with Blocking Method Call
The Task class represents a single operation that usually executes asynchronously. Task object is one of the central components of the task-based asynchronous pattern first introduced in the .NET Framework 4.
Task is more light-weighted than thread. The default task scheduler runs the task inside the thread pool. Therefore, the Task is more suitable to run small, quick asynchronous operations. If you use the Task to run many long-running task, you may use up all the threads in thread pool and new tasks would have to wait for the previous tasks to complete execution.
Creating and Run a Task
The most common to create and execute a task is to use Task.Run() or TaskFactory.StartNew() method.
The main difference between Task.Run and TaskFactory.StartNew is you can pass parameters to the task using TaskFactory.StartNew.
Passing Parameter to a Task
public System.Threading.Tasks.Task StartNew (Action<object?> action, object? state);
One of the overload methods of TaskFactory.StartNew() takes two parameters: The first one is the action delegate to execute asynchronously and the second one (
state) is the parameter passed into the action delegate. The second parameter is the
objecttype. You can pass in any single object as parameter and inside your task cast it back to its original type.
Task class supports cancellation through the use of CancellationTokenSource object. This object has a Token property and a Cancel() method. Following is the how the task cancellation works:
- In the main thread, create a CancellationTokenSource object.
- Pass the CancellationTokenSource.Token property to all the tasks you created.
- Check periodically the CancellationToken.IsCancellationRequested property in the tasks and handle cancellation accordingly.
- In the main thread, call the CancellationTokenSource.Cancel() method. The Cancel() method will set the CancellationToken.IsCancellationRequested property to true.
Cancel Blocking Task
As you can see, the above cancellation mechanism relies on periodically checking the CancellationToken.IsCancellationRequested property. What if my task as a blocking method call? Unfortunately, there is no generic solution for all scenarios.
If the Method Support Begin/End Async API
If the blocking method you are calling also provides asynchronous alternatives, you can utilize the AsyncWaitHandle property of the IAsyncResult returned from the Begin…() method to create a polling situation.
// At this point, asynchronous operation completed
Console.WriteLine("Request processed asyncronously.");
The parameter (1000) in the WaitOne() method is the time out value in milliseconds. The return value false means the time out occurred; the return value of true means the asynchronous operation is completed.
If the method can be interrupted by other operation
This is more specific to the method you are calling. Some methods may support this scenario, some not. Let’s use HttpListener as an example. The HttpListener has a GetContextAsync() method. This method would block the task. However, if you call the HttpListener.Stop() method, it would raise a HttpListenerException and thus unblock the GetContextAsync() method.
How would you call the HttpListener.Stop() method when application is blocked by GetContextAsync() method? You can use the CancellationToken.Register() method to register a delegate that will be called when this CancellationToken is canceled.
Happy coding! Please following me if you can to support my writing.