![](/img/trans.png)
[英]Running a background task and waiting for its result without blocking the UI thread
[英]Waiting for a background worker to finish without blocking UI thread
我有一个应用程序,需要等待后台工作人员完成后才能继续。 后台工作者负责将一些值写入初始化它的USB设备。 后台工作程序的问题在于,我的主程序可以在后台工作程序完成初始化之前尝试访问USB设备。
在后台工作程序工作时,UI线程显示带有动画进度条的“请稍候”。 该进度条不反映多远沿后台工作,它仅仅是“旋转”。
我读过一些问题,说不使用后台工作程序,因为我真的不希望它异步运行(这是对的),但是,如果不使用后台工作程序,我的“请稍候”对话框将阻止并且不会t显示动画。 我也读了很多书,告诉我只能使用一个UI线程,然后该线程支持使用后台工作程序。
我还尝试将“请等待”微调器放在单独的线程中,但这会带来复杂性和奇怪的竞争条件,在这种情况下,“请等待”窗口会在打开之前尝试关闭。
解决这个问题的正确方法是什么?
这正是BackgroundWorker
设计的目的。 尽管还有其他方法可以完成此操作,但是您所做的就很好。
我读了一些问题,说不使用后台工作者
真的不知道为什么人们建议不要使用它,因为它正是为它设计的。 理想情况下,您想要做的是显示一个带有微调框和取消选项的模式对话框,这样,UI会阻止用户中断USB上的写入过程。
即使在写过程中简单地禁用按钮也足够了。
我认为您正在尝试解决两个单独的问题。
第一个是如何防止主(UI)线程访问未初始化的USB设备。 另一个正在处理“请稍候”微调器对话框。
我的建议是:
BackgroundWworker
处理USB设备初始化。 向您的班级添加一个布尔字段,以在USB设备完成初始化时进行标记,例如
private volatile bool _usbDeviceInited = false;
您的后台工作者要做的最后一件事就是将此标志设置为true
。
前面的步骤是解决第一个问题的一种方法。 现在,对于微调器。
我建议您使用BackgroundWorker
的RunWorkerCompleted
事件。 如果您的BackgroundWorker
是从主UI线程创建的,则该事件将在主UIThread中触发(这意味着与用户界面元素进行交互是安全的)。 从那里您可以简单地关闭并放置“请稍候”对话框。 您还应该检查AsyncCompletedEventArgs.Error
属性,以确保在初始化USB设备时,不会从BackgroundWorker线程引发任何错误情况。
编辑:我刚刚读到您的应用程序可能会运行一个脚本,该脚本立即尝试访问USB设备。 使用我建议的模式,您可以在运行脚本之前“轮询”属性,直到它返回的值不同于null,如下所示:
bool timedOut = false;
DateTime timeout = DateTime.Now.AddSeconds(timeoutSeconds);
while ( MyClass.MyUsbDevice == null ) {
if( DateTime.Now > timeout ) {
timedOut = true;
break;
}
Thread.Sleep(0); // Avoid pegging the CPU, yield it to other processes
}
if( !timedOut ) {
// run the script
} else {
// Handle timeout
}
祝好运!
将必须在BackgroundWorker
完成后执行的部分(脚本)放入BackgroundWorker
的RunWorkerCompleted
事件处理程序中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.