Reputation: 1095
I need to show a progress dialog while opening a file, which is a time consuming operation. To do so, I am using following inside my open file function:
//some code
...
...
...
bool done = false;
//Show progress in a separate thread.
System.Threading.ThreadPool.QueueUserWorkItem((x) =>
{
using (var progressDialog = new ProgressDialog())
{
progressDialog.TopMost = true;
progressDialog.Show();
while (!done)
{
if(progressDialog.Message != this.strProgressMsg)
progressDialog.Message = this.strProgressMsg;
Application.DoEvents();
}
progressDialog.Close();
}
});
....
....
done = true;
....
....
The Problem: Progressbar dialog shows up some times and sometimes it doesn't. My file open function runs in the main thread. Can someone please point me in the right detection as why this might be happening?
Upvotes: 1
Views: 477
Reputation: 48949
Forms need a message to work correctly. You can start a message loop with Application.Run
or Form.ShowDialog
both of which are blocking calls so obviously this strategy will not work very well in a worker thread. Here are two ways that you can get it to work correctly.
progressDialog
on the UI thread and send messages to it via Control.Invoke
to update it with new progress information.progressDialog
on the UI thread and have it poll a variable using a System.Windows.Forms.Timer
for new progress information that the worker thread publishes.In this case the polling method is preferred over of the Control.Invoke
method because:
Control.Invoke
imposes.Upvotes: 1
Reputation: 169018
You have this backwards. Here's how it should work:
progressDialog.Invoke()
to perform GUI updates. (It should not set strProgressMsg
and wait for something else to notice the change -- have it send the update straight to the dialog.)So something like this:
using (var progressDialog = new ProgressDialog()) {
progressDialog.TopMost = true;
System.Threading.ThreadPool.QueueUserWorkItem((x) =>
{
try {
// this represents whatever loop you use to load the file
while (...) {
// do some work loading the file
// update the status
progressDialog.Invoke(new MethodInvoker(
() => progressDialog.Message = "Hello, World!"));
}
} finally {
// done working
progressDialog.Invoke(new MethodInvoker(progressDialog.Close));
}
});
// this will block until the thread closes the dialog
progressDialog.ShowDialog();
}
Upvotes: 5