假设我正在向用户展示一个表单,并使用 BackgroundWorker 在幕后做一些工作。
当用户单击“确定”时,在 BackgroundWorker 完成之前我无法继续。如果用户单击确定时它还没有完成,我想显示一个 WaitCursor 直到它完成,然后继续。
实现这一点的最佳方法是什么?
我知道我可以使用一个普通的旧线程,然后执行 Thread.Join,但我喜欢 BackgroundWorker。
可以做得很好吗?
假设我正在向用户展示一个表单,并使用 BackgroundWorker 在幕后做一些工作。
当用户单击“确定”时,在 BackgroundWorker 完成之前我无法继续。如果用户单击确定时它还没有完成,我想显示一个 WaitCursor 直到它完成,然后继续。
实现这一点的最佳方法是什么?
我知道我可以使用一个普通的旧线程,然后执行 Thread.Join,但我喜欢 BackgroundWorker。
可以做得很好吗?
理想情况下,您应该禁用表单上的所有相关控件,然后在完成时重新启用它们BackgroundWorker
。这样你就不会得到一个锁定的 UI - 你可以有一个取消按钮等。
如果您想真正阻塞直到它完成,您可以同步运行任务以开始。
您可以使用此代码,而不是 BW
var resetEvent = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(state =>
{
Thread.Sleep(5000);//LongRunning task, async call
resetEvent.Set();
});
resetEvent.WaitOne();// blocking call, when user clicks OK
您可以通过检查 btnOK_Click 事件处理程序来检查 BackgroundWorker 是否正在运行,以查看 bw.IsBusy 是否为真。如果是这样,请更改光标并设置一个布尔标志,指示 OK 处理程序正在等待。当 BackgroundWorker 完成其工作时,检查是否 ok 一直在等待,如果是,则将标志设置为 false 更改光标并执行 OK 按钮的工作。:-)
我只会使用布尔标志和锁。
object waitlock = new object();
bool isBackgroundWorkerCompleted = false;
bool isOKButtonPressed = false;
private void onPress(...)
{
lock(waitlock)
{
isOKButtonPressed = true;
if (isBackgroundWorkerCompleted) DoNextStep();
else cursor.Wait(); //psuedo-code - use whatever the actual call is...
}
}
后台线程执行相同的技巧(只需记住 BeginInvoke 回到主 UI 线程)