Tim Van Wassenhove

Passionate geek, interested in Technology. Proud father of two

27 Apr 2007

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.

screenshot of ildasm displaying generated performer class

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

screenshot of application not doing anything

screenshot of application performing long running task

screenshot of application after completion of long running task

Feel free to download the AsyncDemo.zip