Another option is to use an asynchronous delegate to show the form on a threadpool thread.
Threads in the threadpool are recommended for shorter lived threads that do not last for the entire application duration. As this is to display a short-lived please wait window, the threadpool is a reasonable choice.
The Action delegate (.NET 2.0+) is used along with it's BeginInvoke() method to automatically run the delegate code on a threadpool thread.
Some notes:
- It is important to use Control.BeginInvoke for any cross thread GUI calls, such as closing the please wait form in ClosePleaseWait().
- Also, the
m_pleaseWaitForm.ShowDialog();
actually starts a new message loop in the new thread. This is what keeps the please wait form alive.
- Because a threadpool thread is used, this thread is automatically a background thread and will be terminated if the main application is closed.
- Apart from running on another thread, there is nothing special about Form2. You can place any child controls such as Pictureboxes, labels etc on it.
(MethodInvoker)delegate { ... }
is just a .NET 2.0 way of running code in a delegate inline.
The example below can be added to a WinForms project containing Form1: the main form, and Form2: the please wait form.
private Form2 m_pleaseWaitForm = null;
private void Form1_Shown(object sender, EventArgs e)
{
// This code could also be placed in eg. a button click event handler.
Action<Rectangle> a = new Action<Rectangle>(ShowPleaseWait);
a.BeginInvoke(this.Bounds, null, null);
// Do your long running tasks
ClosePleaseWait();
}
private void ShowPleaseWait(Rectangle bounds)
{
// This method runs on the new thread.
m_pleaseWaitForm = new Form2();
m_pleaseWaitForm.TopMost = true;
m_pleaseWaitForm.Location = new Point(bounds.Left + bounds.Width / 2 - m_pleaseWaitForm.Width / 2, bounds.Top + bounds.Height / 2 - m_pleaseWaitForm.Height / 2);
m_pleaseWaitForm.ShowDialog();
}
private void ClosePleaseWait()
{
m_pleaseWaitForm.BeginInvoke((MethodInvoker)delegate { m_pleaseWaitForm.Close(); });
}