【问题标题】:How to program asynchronous Windows Forms Applications?如何编写异步 Windows 窗体应用程序?
【发布时间】:2009-10-04 20:47:13
【问题描述】:

我正在用 C# 编写一个Windows Forms 应用程序,它执行许多长时间运行的过程。我需要对应用程序进行编程,以便 GUI 不会锁定。最好的编程方法是什么?

我知道如何使用以下内容:

  1. BeginInvoke/EndInvoke
  2. 反复调用Application.DoEvents()(可能不是一个好主意)
  3. BackgroundWorker
  4. 等

但是如何通过回调等管理 GUI 状态并非易事。是否有解决方案(以模式或库的形式)?

【问题讨论】:

    标签: c# .net winforms user-interface


    【解决方案1】:

    使用BackgroundWorker 是执行您想做的事情的最简单方法。 BackgroundWorker 简化了处理线程的逻辑,只需要编写很少的代码。您只需处理三个事件(DoWork、ProgressChanged 和 RunWorkerCompleted)并遵循一些原则:

    • 永远不要在您的长时间运行的方法中更新 UI。让它改为调用 ReportProgress 并在 UI 逻辑中处理 ProgressChanged 事件。
    • 请理解,由于工作线程未在 UI 线程上运行,因此您的方法引发的异常不会自动显示在 UI 中。它只是默默地写入控制台。当方法完成并处理(或抛出)异常时,检查RunWorkerCompletedEventArgs 的Error 属性非常重要。如果你不这样做,你就不会知道你的方法失败了。
    • 如果可以取消该方法,请确保它定期检查CancellationPending 属性以查看是否已请求取消。如果有,一旦处理完取消,在DoWorkEventArgs 对象上设置Cancel 属性。请注意,CancellationPending 可能为真,Cancel 可能为假;例如,当用户请求取消并且该方法在有机会检查CancellationPending 之前完成时,就会发生这种情况。
    • 相应地,在您的 RunWorkerCompleted 事件处理程序中检查 Cancel,以便您的 UI 可以对工作器运行时发生的事情提供正确的响应。

    文档中的示例都显示了DoWork 事件处理程序调用表单的方法。这几乎肯定不是您想要做的。将业务逻辑与 UI 分离通常是一个好主意;在后台任务中它是必不可少的。如果您的长时间运行的方法是一个甚至不知道 UI 存在的类的成员,那么您不会不小心让它调用一个更新状态栏或其他东西的方法。

    【讨论】:

      【解决方案2】:

      Model-View-Controller pattern 将 UI 的状态与 UI 的视觉方面分开。只要您的 MVC 实现是线程感知的,它就应该为您解决状态管理问题。

      这就是我处理多线程 UI 实现的方式。

      编辑:这是一个good post,关于为 WinForms 项目选择 MVC 实现。

      【讨论】:

      • 啊哈……这就是 MVC 的用途。好的.. 非常感谢。
      【解决方案3】:

      使用 ThreadPool 从 UI 触发长时间运行的进程相对简单。如果您需要反馈,您可以使用一些事件处理程序来触发长期运行进程中的某些事件,然后注册它们并根据需要更新 UI。

      MVC 很好,但您仍然需要确保您的进程是在 UI 线程之外的线程上触发的。

      【讨论】:

        【解决方案4】:

        你所有的选择都是做同样事情的语法糖(异步执行)。可能具有不同级别的控件。我会选择 BackgroundWorker,因为您的 GUI(由主线程处理)将始终响应。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-01-19
          • 2016-07-09
          • 1970-01-01
          • 2015-04-17
          • 1970-01-01
          • 2023-03-27
          相关资源
          最近更新 更多