Performing long running tasks in a Windows Application
A while ago i blogged about Thread Safe UI. Today someone asked the following
The first thing i do is define a delegate (void Performer()) that will do the work of a long running operation. The reason i do this is because the compiler generates a class Performer that inherits from System.MulticastDelegate and exposes Begin- and EndInvoke methods.
Since i want to disable my form before each run of a Performer and enable it after each run i implement a method Perform as following
private void Perform(Performer performer, string message)
{
this.PrePerform(message);
performer.BeginInvoke(this.PostPerform, null);
}
Now it’s simply a matter of implemeting Pre- and PostPerform
private void PrePerform(string message)
{
if (this.InvokeRequired)
{
this.EndInvoke(this.BeginInvoke(new MethodInvoker(delegate { this.PrePerform(message); })));
}
else
{
this.Enabled = false;
this.toolStripStatusLabel1.Text = message;
this.toolStripStatusLabel1.Visible = true;
this.toolStripProgressBar1.Visible = true;
}
}
private void PostPerform(object state)
{
if (this.InvokeRequired)
{
this.EndInvoke(this.BeginInvoke(new MethodInvoker(delegate { this.PostPerform(state); })));
}
else
{
this.toolStripProgressBar1.Visible = false;
this.toolStripStatusLabel1.Visible = false;
this.toolStripStatusLabel1.Text = string.Empty;
this.Enabled = true;
}
}
Now that we have all the infrastructure i implement an eventhandler for a button click
private void button1_Click(object sender, EventArgs e)
{
// remove previously retrieved results
this.UpdateResultLabel(string.Empty);
this.Perform(delegate
{
// simulate the effect of a blocking operation that takes a while to complete
// eg: remoting, webrequests, database queries, ...
Thread.Sleep(5000);
// display the result of the long running operation
this.UpdateResultLabel("Value was retrieved...");
}, "Retrieving value...");
}
Here are a couple of screenshots of the running program
Feel free to download the AsyncDemo.zip