1

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

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

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

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

解决这个问题的正确方法是什么?

4

4 回答 4

4

这正是BackgroundWorker设计的目的。尽管还有其他方法可以做到这一点,但您所做的一切都很好。

于 2012-11-06T16:02:09.077 回答
3

我读过一些问题,说不要使用后台工作人员

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

甚至在写入过程中简单地禁用按钮就足够了。

于 2012-11-06T16:02:18.680 回答
2

我认为您正在尝试解决两个不同的问题。

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

我的建议是:

  1. 继续BackgroundWworker处理 USB 设备初始化。
  2. 向您的类添加一个布尔字段,以标记 USB 设备何时完成初始化,例如

    private volatile bool _usbDeviceInited = false;

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

  4. 通过属性集中访问 USB 设备。如果 USB 初始化尚未完成,getter 方法可以检查布尔字段并返回空值(或者如果您愿意,可以引发异常)。
  5. 修改您的代码以检查是否由授予对 USB 设备的访问权限的属性返回 null(或处理异常,如果您选择引发一个),这意味着它尚未准备好使用。您可以处理此情况以提醒用户 USB 设备未准备好。

前面的步骤是解决第一个问题的一种方法。现在,对于微调器。

我建议订阅RunWorkerCompleted你的事件BackgroundWorker。如果您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
}

祝你好运!

于 2012-11-06T16:29:28.393 回答
2

BackgroundWorker完成后必须执行的部分(-脚本)放入BackgroundWorkerRunWorkerCompleted事件处理程序中。

于 2012-11-06T16:30:22.477 回答