Asynchronous Method Progress Reporting [C#]
This example demonstrates how to report progress information and intermediate results from an asynchronous method. It builds on a previous example, Create an Asynchronous Method.
This example is part of asynchronous method implementation series.
We do the following modifications in the code from the example mentioned above:
- modify the MyTaskWorker to report progress every second
- implement the MyTaskProgressChanged event with event data of type MyTaskProgressChangedEventArgs.
MyTaskWorker
This is MyTaskWorker as it is defined in the Create Asynchronous Method example.
[C#]private void MyTaskWorker(string[] files) { foreach (string file in files) { // a time consuming operation with a file (compression, encryption etc.) Thread.Sleep(1000); } }
Now, we modify it so it notifies the client code of progress percentage and an already processed file. Notice the AsyncOperation added to method's parameters.
[C#]private void MyTaskWorker(string[] files, AsyncOperation async) { for (int i = 0; i < files.Length; i++) { // a time consuming operation with a file (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 Thread.Sleep(1000)
statement), we compute the progress in percents 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 fire 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.
private delegate void MyTaskWorkerDelegate(string[] files, AsyncOperation async); public void MyTaskAsync(string[] files) { // ... worker.BeginInvoke(files, async, completedCallback, async); // ... }
You might ask if 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.
[C#]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 comes the definition of MyTaskProgressChangedEventArgs:
[C#]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; } }
Notice 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:
[C#]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); }
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
- AsyncOperation.Post – MSDN – sends event to the client code
- ProgressChangedEventArgs – MSDN – event data for basic progress reporting
- ProgressChangedEventHandler – MSDN – event handler for basic progress reporting
- Thread.Sleep – MSDN – suspends a thread