Multi Threading - How to report Asynchronous Method Progress/Status?
Asynchronous Method Progress Reporting
This example explains how to report progress information and intermediate
results from an asynchronous method. It builds on a previous example, Create an Asynchronous Method.
We will do the following modifications in the code from the example mentioned above:
This method is same as defined in previous example Create Asynchronous Method.
Code:
We will do the following modifications in the code from the example mentioned above:
- modify the MyTaskWorker to report progress every one second
- implement the MyTaskProgressChanged event with event data of type MyTaskProgressChangedEventArgs.
MyTaskWorker
This method is same as defined in previous example Create Asynchronous Method.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); } }
Now we will modify this as it notifies the client code about progress
percentage and an already processed file. Notice the
AsyncOperation
added to method's parameters.
Code:
Code:
private void MyTaskWorker(string[] files, AsyncOperation async) { for (int i = 0; i < files.Length; i++) { // a time consuming operation with a file (copy, compression, encryption etc.) Thread.Sleep(1000); // compute progress int progressPercentage = 100 * (i + 1) / files.Length; // raise the progress changed event MyTaskProgressChangedEventArgs eArgs = new MyTaskProgressChangedEventArgs( progressPercentage, files[i], null); async.Post(delegate(object e) { OnMyTaskProgressChanged((MyTaskProgressChangedEventArgs)e); }, eArgs); } }
After processing a file (the
Then, we fired the ProgressChanged event using the AsyncOperation object.
We also have to add the
Code:
You may get doubt that, is two asyncs in BeginInvoke parameters are correct. Yes, they are.
The first async is passed to MyTaskWorker as its second parameter. The second async is stored into IAsyncResult instance that is passed to MyTaskCompletedCallback.
This event is raised whenever the asynchronous method wants to report
progress to the client code.
Thread.Sleep(1000)
statement), we compute the progress in percentage and store it to
MyTaskProgressChangedEventArgs together with the current file
name, which is an example of an intermediate result sent to the client
code.Then, we fired the ProgressChanged event using the AsyncOperation object.
We also have to add the
AsyncOperation async
parameter to the
MyTaskWorkerDelegate and update the
BeginInvoke statement in the MyTaskAsync
method.Code:
private delegate void MyTaskWorkerDelegate(string[] files, AsyncOperation async); public void MyTaskAsync(string[] files) { // ... worker.BeginInvoke(files, async, completedCallback, async); // ... }
You may get doubt that, is two asyncs in BeginInvoke parameters are correct. Yes, they are.
The first async is passed to MyTaskWorker as its second parameter. The second async is stored into IAsyncResult instance that is passed to MyTaskCompletedCallback.
MyTaskProgressChanged event
This event is raised whenever the asynchronous method wants to report
progress to the client code.
Code:
public event EventHandler<MyTaskProgressChangedEventArgs> MyTaskProgressChanged; protected virtual void OnMyTaskProgressChanged(MyTaskProgressChangedEventArgs e) { if (MyTaskProgressChanged != null) MyTaskProgressChanged(this, e); }
The MyTaskProgressChangedEventArgs used by the event
handler define a data member for storing the name of the last processed file. If
you don't need to report such results, use ProgressChangedEventHandler
as the event data type.
Here is the definition of MyTaskProgressChangedEventArgs,
Code:
public class MyTaskProgressChangedEventArgs : ProgressChangedEventArgs { private string _currentFile; public string CurrentFile { get { return _currentFile; } } public MyTaskProgressChangedEventArgs(int progressPercentage, string currentFile, object userState) : base(progressPercentage, userState) { _currentFile = currentFile; } }
Observe that MyTaskProgressChangedEventArgs inherits from ProgressChangedEventArgs
and that the CurrentFile data member is declared as
read-only.
Handling the MyTaskProgressChanged event
Register and implement a handler of the MyTaskProgressChanged event.
Code:
Code:
myObj.MyTaskProgressChanged += new EventHandler<MyTaskProgressChangedEventArgs>(myObj_MethodProgressChanged); void myObj_MethodProgressChanged(object sender, MyTaskProgressChangedEventArgs e) { Console.WriteLine("[MyTask] Progress: {0} %, Current file: {1}", e.ProgressPercentage, e.CurrentFile); }
If you feel this is helpful or you like it, Please share this using share buttons available on page.
Comments
Post a Comment