我需要在打开文件时显示进度对话框,这是一项耗时的操作。为此,我在我的打开文件函数中使用了以下内容:
//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;
....
....
问题: 进度条对话框显示一些时间,有时则不显示。我的文件打开功能在主线程中运行。有人可以指出我正确的检测,为什么会发生这种情况?
答案 0 :(得分:5)
你有这种倒退。这是它应该如何工作:
progressDialog.Invoke()
回调主线程以执行GUI更新。 (它不应该设置strProgressMsg
并等待其他事情注意到更改 - 让它直接将更新发送到对话框。)这样的事情:
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();
}
答案 1 :(得分:1)
表单需要一条消息才能正常工作。您可以使用Application.Run
或Form.ShowDialog
启动一个消息循环,这两个消息都是阻塞调用,所以很明显这个策略在工作线程中不能很好地工作。您可以通过以下两种方式使其正常工作。
progressDialog
并通过Control.Invoke
向其发送消息,以使用新的进度信息对其进行更新。progressDialog
,并使用System.Windows.Forms.Timer
轮询变量,以获取工作线程发布的新进度信息。在这种情况下,轮询方法优于Control.Invoke
方法,因为:
Control.Invoke
强加的UI和工作线程之间的紧密耦合。