Cancel an Asynchronous Method [C#]
This example shows how to implement support for asynchronous method cancellation in your class. It is based on the Create an Asynchronous Method example.
This example is part of asynchronous method implementation series.
We implement a CancelAsync method that signals the asynchronous worker to cancel the operation. This is done by setting a boolean variable that is periodically checked by the asynchronous worker. When the asynchronous worker receives the cancel signal, it finishes and fires the MyTaskCompleted event with the Cancelled flag set.
MyAsyncContext class
To signal the worker, we need an object with a boolean property. This property will be set by the CancelAsync method and periodically checked by the asynchronous worker.
[C#]internal class MyAsyncContext { private readonly object _sync = new object(); private bool _isCancelling = false; public bool IsCancelling { get { lock (_sync) { return _isCancelling; } } } public void Cancel() { lock (_sync) { _isCancelling = true; } } }
We add a member of the MyAsyncContext type to our class.
[C#]private MyAsyncContext _myTaskContext = null;
This member is set in the MyTaskAsync method when the asynchronous operation is invoked. The same MyAsyncContext instance is passed also to the asynchronous worker.
[C#]public void MyTaskAsync(string[] files) { MyTaskWorkerDelegate worker = new MyTaskWorkerDelegate(MyTaskWorker); AsyncCallback completedCallback = new AsyncCallback(MyTaskCompletedCallback); lock (_sync) { if (_myTaskIsRunning) throw new InvalidOperationException("The control is currently busy."); AsyncOperation async = AsyncOperationManager.CreateOperation(null); MyAsyncContext context = new MyAsyncContext(); bool cancelled; worker.BeginInvoke(files, context, out cancelled, completedCallback, async); _myTaskIsRunning = true; _myTaskContext = context; } } private readonly object _sync = new object();
Asynchronous code modifications
The asynchronous worker must be modified to support cancellation. As you could notice in MyTaskAsync code, we added one input parameter of type MyAsyncContext and one output boolean parameter. The latter one indicates, whether the operation has been cancelled, when the worker finishes.
[C#]private void MyTaskWorker(string[] files, MyAsyncContext asyncContext, out bool cancelled) { cancelled = false; foreach (string file in files) { // a time consuming operation with a file (compression, encryption etc.) Thread.Sleep(1000); if (asyncContext.IsCancelling) { cancelled = true; return; } } } private delegate void MyTaskWorkerDelegate(string[] files, MyAsyncContext asyncContext, out bool cancelled);
The worker periodically test the asyncContext.IsCancelling
property. If the property is set to true, the output parameter
cancelled
is set and the method is finished.
The value of the cancelled
parameter is copied to the AsyncCompletedEventArgs.Cancelled
property in asynchronous operation completed callback.
private void MyTaskCompletedCallback(IAsyncResult ar) { // get the original worker delegate and the AsyncOperation instance MyTaskWorkerDelegate worker = (MyTaskWorkerDelegate)((AsyncResult)ar).AsyncDelegate; AsyncOperation async = (AsyncOperation)ar.AsyncState; bool cancelled; // finish the asynchronous operation worker.EndInvoke(out cancelled, ar); // clear the running task flag lock (_sync) { _myTaskIsRunning = false; _myTaskContext = null; } // raise the completed event AsyncCompletedEventArgs completedArgs = new AsyncCompletedEventArgs(null, cancelled, null); async.PostOperationCompleted( delegate(object e) { OnMyTaskCompleted((AsyncCompletedEventArgs)e); }, completedArgs); }
CancelAsync method
This method signals the asynchronous worker to cancel the operation. It uses the MyAsyncContext instance that was created during asynchronous operation invokation.
[C#]public void CancelAsync() { lock (_sync) { if (_myTaskContext != null) _myTaskContext.Cancel(); } }
Note: If you have only one asynchronous method in your class, consider renaming the CancelAsync method to a name similar to MyTaskAsyncCancel. All the asynchronous operation related methods will then be displayed together in Visual Studio.
In this series
- [C#] Create an Asynchronous Method – how to create an asynchronous method
- [C#] Asynchronous Method Progress Reporting – how to report progress
- [C#] Cancel an Asynchronous Method – implement cancellation support
See also
- [C#] Create New Thread – how to create a new thread
- Multithreaded Programming with the Event-based Asynchronous Pattern – MSDN
- Calling Synchronous Methods Asynchronously – MSDN – asynchronous programming using delegates
- AsyncComepletedEventArgs – MSDN – data for AsyncCompleted event
- AsyncComepletedEventHandler – MSDN – handler of the AsyncCompleted event