A Short and Easy Introduction to .NET's Task Class
Task.Run
You can use Task.Run to schedule a delegate to run on the thread pool. The method returns a new task, and if the work is complete, the result will be available via Task.Result. If not, Task.Result will block until it is complete.
private void button_Click(object sender, EventArgs e)
{
Task<DateTime> task = Task.Run(() => GetDateTime());
lblDateTime.Text = task.Result.ToString();
}
private DateTime GetDateTime()
{
// Simulate a blocking task.
Thread.Sleep(2000);
return DateTime.Now;
}
Task.ContinueWith
You'll want to avoid accessing the Task.Result property because it will block until the result is ready. In the previous example, the UI will hang for about 2000 milliseconds before updating the label with the result. You can fix this with Task.ContinueWith.
private void button_Click(object sender, EventArgs e)
{
Task<DateTime> task = Task.Run(() => GetDateTime());
task.ContinueWith(t => lblDateTime.Text = t.Result.ToString());
}
private DateTime GetDateTime()
{
// Simulate a blocking task.
Thread.Sleep(2000);
return DateTime.Now;
}
In this case Task.Result will not block because ContinueWith runs after the first task is complete; however, this code will throw an exception.
An exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll but was not handled in user code
Additional information: Cross-thread operation not valid: Control 'lblDateTime' accessed from a thread other than the thread it was created on.
You can only update the UI from the thread that created the form. Remember Control.Invoke in WinForms? Fortunately, you can fix it by creating an instance of TaskScheduler from the UI thread's SynchronizationContext and using it when invoking ContinueWith.