Introduction
This article describes how to call a long running method asynchronously on a separate thread and also display a wait image until the thread is not done executing a task.
Background
There have been many situations where developers have to run a function/method/programming logic that takes substantially longer than usual. In that case, it's always recommended to run it asynchronously in a separate thread and also display a wait message/image to the end user. This sample application will explain how this can be achieved.
Using the Code
First, I have declared two delegates in class Form1
. LoadDataDelegate
is used to call the long running method asynchronously, and it takes the key as a parameter (just to show a parameterized sample). DisplayWaitDelegate
is used to display/hide the wait image. It takes a boolean parameter to set whether to display or hide.
delegate void LoadDataDelegate(string key);
delegate void DisplayWaitDelegate(bool boolDisplay);
The following code is in my Load Data button click event. I will explain the function DisplayWait
later, but this is used to display the wait image. The function "LoadData
" in Class1
takes longer to execute, so I have instantiated the LoadDataDelegate
delegate and passed in this function name. Finally, call BeginInvoke
to start. Notice the second parameter which is a function name (which is explained later) is called when this asynchronous call / thread is completed.
private void btnLoadData_Click(object sender, EventArgs e)
{
DisplayWait(true);
string key = textBox1.Text;
Class1 objClass1 = new Class1();
LoadDataDelegate delLoadData = new LoadDataDelegate(objClass1.LoadData);
delLoadData.BeginInvoke(key, this.LoadComplete, delLoadData);
}
Following is the code for the LoadComplete
function. This function gets the handle for the delegate and calls the EndInvoke
method to stop the asynchronous call. The function DisplayWait
is called again, but this time with the parameter boolean value as false
, which hides the wait image.
private void LoadComplete(IAsyncResult ar)
{
LoadDataDelegate d = (LoadDataDelegate)ar.AsyncState;
d.EndInvoke(ar);
DisplayWait(false);
MessageBox.Show("Data Load Completed.");
}
Following is the code for the DisplayWait
function. The pcitureBox1
control contains the wait image. The InvokeRequired
call is needed to ensure this program doesn't cause any cross thread exception. Again, create an instance of DisplayWaitDelegate
and pass the same method name "DisplayWait". Then call the Invoke
method of the control (in this case, pictureBox1
) and pass the delegate instance and parameters in an array of object
s (in this case, just one parameter).
Now, this will call the function DisplayWait
again, and this time, it will go in the else
block, and there I'm setting up the visibility. I'm also setting up the UseWaitCursor
property at the Form
level to display the hour glass when the wait image is being displayed.
private void DisplayWait(bool boolDisplay)
{
if (pictureBox1.InvokeRequired)
{
DisplayWaitDelegate del = new DisplayWaitDelegate(DisplayWait);
pictureBox1.Invoke(del, new object[] { boolDisplay });
}
else
{
pictureBox1.Visible = boolDisplay;
UseWaitCursor = boolDisplay;
}
}
Now the last but not the least, the function "LoadData
" in Class1
, which is nothing but Thread.Sleep(10000)
to show a sample delay of 10 seconds with this application.
public void LoadData(string key)
{
Thread.Sleep(10000);
}
Points of Interest
This can also be extended to show a progress bar.
History