等待后台工作程序完成而不阻止UI线程

时间:2012-11-06 15:57:06

标签: c# multithreading backgroundworker

我有一个应用程序,需要等待后台工作程序完成才能继续。后台工作人员负责将一些值写入初始化它的USB设备。后台工作程序的问题是我的主程序可以在后台工作程序完成初始化之前尝试访问USB设备。

当后台工作人员正在工作时,UI线程显示“请稍候”并带有动画进度条。进度条反映背景工作者的距离,它只是“旋转”。

我已经阅读了一些不使用后台工作程序的问题,因为我真的不希望它以异步方式运行(这是真的),但是,如果不使用后台工作程序,我的“请稍候”对话框块并且不显示动画。我还阅读了很多,告诉我只使用一个UI线程,然后支持使用后台工作程序。

我还尝试将“请等待”微调器放在一个单独的线程中,但这会引入复杂性和奇怪的竞争条件,其中“请等待”窗口在打开之前尝试关闭。

正确的方法是什么?

4 个答案:

答案 0 :(得分:4)

这正是BackgroundWorker的设计目标。虽然还有其他方法可以做到这一点,但你正在做的事情很好。

答案 1 :(得分:3)

  

我已经阅读了一些不使用后台工作者的问题

不知道为什么人们建议使用它,因为它正是它的设计目的。理想情况下,您想要做的是显示带有微调器的模态对话框和取消选项,这样用户就会阻止用户中断USB上的写入过程。

即使只是在写入过程中禁用按钮就足够了。

答案 2 :(得分:2)

我认为您要解决的问题有两个。

第一个是如何防止Main(UI)线程访问未初始化的USB设备。另一个是处理“请等待”微调器对话框。

我的建议是:

  1. 保持BackgroundWworker处理USB设备初始化。
  2. 在类中添加一个布尔字段,以标记USB设备何时完成初始化 e.g。

    private volatile bool _usbDeviceInited = false;

  3. 后台工作人员将做的最后一件事,是将此标志设置为true

  4. 通过属性集中访问USB设备。如果USB初始化尚未完成,则getter方法可以检查布尔字段并返回空值(如果您愿意,则返回异常)。
  5. 修改您的代码以检查是否正在返回null(或者如果您选择引发异常,则处理异常),该属性允许访问USB设备,这意味着它尚未准备好使用。您可以处理此情况以提醒用户USB设备尚未就绪。
  6. 前面的步骤是解决第一个问题的一种方法。 现在,对于微调器。

    我建议您怀疑RunWorkerCompleted的{​​{1}}事件。如果您的BackgroundWorker是从主UI线程创建的,则事件将在主UIThread中触发(意味着可以安全地与用户界面元素进行交互)。从那里你可以简单地关闭并处理你的“请等待”对话框。您还应该检查BackgroundWorker属性,以确保在初始化USB设备时没有从BackgroundWorker线程引发错误情况。

    修改 我刚看到您的应用程序可能会运行一个立即尝试访问USB设备的脚本。使用我建议的模式,您可以在运行脚本之前“轮询”该属性,直到它返回一个不同于null的值,如下所示:

    AsyncCompletedEventArgs.Error

    祝你好运!

答案 3 :(得分:2)

BackgroundWorker完成之后必须执行的部分( - 脚本)放在BackgroundWorker的{​​{1}}事件处理程序中。