Parallel programming is introduced in C# 4.0 using the Task libraries. There are many aspects of Parallel programming and how to use the Task libraries. Here, we will look into the Task from a beginner stand point. In this article, we will discuss about how to create an asynchronous method using Task.
Asynchronous Method
Task is a generic class defined under System.Threading.Tasks namespace. In this article we are looking into only one aspect of task, how to create an asynchronous method using the Task.
Method
First, we define our work in a method. For our sample, I am using the method called Work, which return a string data.
public string Work(string data)
{
data += "\nThread Id Inside Work : " +
Thread.CurrentThread.ManagedThreadId.ToString();
Thread.Sleep(1000);
return data;
}
This is a simple method, which takes one string value as input, add the current thread Id to the string data and wait for one second.
Begin Async Method
Now, let us define our first method which starts the operation.
public IAsyncResult BeginWork(string data, AsyncCallback callBack, object state)
{
Task<string> task=new Task<string>((obj)=>{
return Work(data);
}, state);
if (callBack != null)
{
task.ContinueWith((tsk) => callBack(tsk));
}
task.Start();
return task;
}
This method is the begin method of our Asynchronous method. As it is an asynchronous method start, it should return the result as IAsyncResult.
Here, we passed three values to the method.
-
Data: holding the thread Ids.
-
Callback method: Once the task completes its execution, it will execute the callback method.
-
State: specifies the status of the asynchronous method.
Our sample method returns a string, so created an object of Task class taking string type. Task constructor accepts the method name and the state information.
If we specified any callback method, task.ContinueWith() will continue the execution with the callback method.
End Async Method
Now define the completion method. This will take the IAsyncResult as the argument, which holds the result of the asynchronous method execution. If there is any exception occurs in the execution, IAsyncResult will have the corresponding exception detail.
public virtual string EndWork(IAsyncResult result)
{
string data=string.Empty;
Task<string> task = result as Task<string>;
if (task != null)
{
data = task.Result;
}
data += "\nThread Id Inside End Work : " +
Thread.CurrentThread.ManagedThreadId.ToString();
return data;
}
Convert the result into the corresponding task format. Task.Result will yield the return value of the asynchronous method. In our sample, extracted the result from the IAsyncResult and added the current thread Id to the result.
Main Application
For verifying the asynchronous method, I am using one windows application. On the button click event, invoke the asynchronous method defined in the Util class.
private void button1_Click(object sender, EventArgs e)
{
data ="Thread Id Before Start : " + Thread.CurrentThread.ManagedThreadId.ToString();
utilObj.BeginWork(data, Callback, null);
}
In callback method, call the end method of the asynchronous method and show the result.
void Callback(IAsyncResult result)
{
string message = utilObj.EndWork(result);
message += "\nThread Id Inside Callback : " + Thread.CurrentThread.ManagedThreadId.ToString();
MessageBox.Show(message);
}
Result
There are two threads used by the asynchronous operation. One is the UI thread, which will be part of the button click event and the other is used by the task execution.

TaskScheduler
We are using a workflow application, which will run on the UI thread itself using the SynchronizationContext. The asynchronous operation is for performing some action on the workflow. Workflow execution should be in a single thread. For ensuring this scenario, we need to run the asynchronous method using the UI thread.
For achieving this, we used the TaskScheduler, which gets the thread information from the Current synchronization context. Task is started using the scheduler to use the UI thread for the method.
public IAsyncResult BeginWork(string data, AsyncCallback callBack, object state)
{
TaskScheduler scheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task<string> task=new Task<string>((obj)=>{
return Work(data);
}, state);
if (callBack != null)
{
task.ContinueWith((tsk) => callBack(tsk));
}
task.Start(scheduler);
return task;
}
Result
Now, observe the result, where the UI operation (button click) and the asynchronous method execution is in the same thread. Callback method execution is in another thread.
Conclusion
Parallel programming using Task libraries are very powerful and flexible. In this article we discussed about how to create an asynchronous operation using Task and how to use the UI thread as part of the Task execution using TaskScheduler.