(Multi Threading) How to invoke an asynchronous method
This example shows how to create/Invoke an asynchronous method conforming to the Event-based
Asynchronous pattern
In this example, we will create an asynchronous method that processes
a list of files.
private void MyTask(string[] files) { foreach (string file in files) { // a time consuming operation with a file (copy, compression, encryption etc.) Thread.Sleep(1000); } }
The asynchronous method implementation consists of the following members:
- MyTaskWorker method – does the actual work
- IsBusy property – indicates that an asynchronous operation is running
- MyTaskAsync method – invokes the asynchronous operation
- MyTaskCompletedCallback method – called when MyTaskWorker completes
- MyTaskCompleted event – notifies of the asynchronous operation completion.
Notice that, how members names are derived from the original method name(MyTask). This is
the recommended way.
Now we will see the how to achieve the above mentioned,
MyTaskWorker method
This method will execute on background and does the actual work of the
original synchronous method. In this example, it doesn't differ from the
original method. Notice that we also provide a delegate definition for this
method.
Code:
Code:
private void MyTaskWorker(string[] files) { foreach (string file in files) { // a time consuming operation with a file (copy, compression, encryption etc.) Thread.Sleep(1000); } } private delegate void MyTaskWorkerDelegate(string[] files);
IsBusy property
This property indicates a running asynchronous operation. Implementation of
this property is needed, when concurrent invocations of asynchronous operations
are not supported.
Code:
private bool _myTaskIsRunning = false; public bool IsBusy { get { return _myTaskIsRunning; } }
MyTaskAsync method
This method invokes the asynchronous operation and immediately
returns. If an asynchronous operation is already running, an
InvalidOperationException is thrown.
Code:
Code:
private readonly object _sync = new object(); 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); worker.BeginInvoke(files, completedCallback, async); _myTaskIsRunning = true; } }
First, an AsyncOperation
is created. This object is used by the worker thread to invoke
client's event handlers on the proper thread or context for the given
application model.
Next, the asynchronous operation is started in a separate thread by the BeginInvoke method. Besides the files parameter, the BeginInvoke method has two additional parameters:
This method calls worker delegate's EndInvoke method to finish the
asynchronous operation and raises the MyTaskCompleted event.
Code:
Next, the asynchronous operation is started in a separate thread by the BeginInvoke method. Besides the files parameter, the BeginInvoke method has two additional parameters:
- A delegate of type AsyncCallback to a callback method that is called when the asynchronous operation completes.
- A custom object that is stored in the AsyncState property of an IAsyncResult instance returned by the BeginInvoke method. The same instance of IAsyncResult is also passed to the callback method.
MyTaskCompletedCallback method
This method calls worker delegate's EndInvoke method to finish the
asynchronous operation and raises the MyTaskCompleted event.Code:
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; // finish the asynchronous operation worker.EndInvoke(ar); // clear the running task flag lock (_sync) { _myTaskIsRunning = false; } // raise the completed event AsyncCompletedEventArgs completedArgs = new AsyncCompletedEventArgs(null, false, null); async.PostOperationCompleted( delegate(object e) { OnMyTaskCompleted((AsyncCompletedEventArgs)e); }, completedArgs); }
In the above code operations are performed in following sequence,
1. the original worker delegate instance and the
AsyncOperation object are obtained.
2. EndInvoke is
called to free resources held by the asynchronous operation.
3. MyTaskCompleted event is fired through the AsyncOperation
object.
MyTaskCompleted event
This event is raised when the asynchronous operation is completed.
Code:
Code:
public event AsyncCompletedEventHandler MyTaskCompleted; protected virtual void OnMyTaskCompleted(AsyncCompletedEventArgs e) { if (MyTaskCompleted != null) MyTaskCompleted(this, e); }
That's it. Now we are done with creation of Asynchronous method.
If you feel this is helpful or you like it, Please share this using share buttons available on page.
Comments
Post a Comment