【问题标题】:How to handle control updates while doing processing?处理时如何处理控件更新?
【发布时间】:2012-02-09 08:16:50
【问题描述】:

我正在编写一个小型 .NET(Windows 窗体)应用程序,但我似乎无法正确处理多线程。

应用程序有一个非常简单的逻辑:它显示一个主窗体,其中包含一些要填写的参数、一个开始处理的按钮和一个进度条;当用户单击按钮时开始处理,在程序运行时应该更新进度条,一些MessageBoxes可以在处理时弹出以显示警告/信息,当处理结束时另一个MessageBox会弹出结果。相当简单......但我似乎无法找到正确处理控件更新的方法。

首先我尝试了简单的路线:在 Button_Clicked 事件中进行所有处理。这并不顺利:它起作用了,但是表单在处理时变得完全没有响应,它根本不关心任何用户点击。我认为这是因为它实际上正忙于处理一个事件,因此停止处理其他事件......所以我选择了多线程。

在按钮处理事件中,我启动了一个新的Thread 并使其进行处理,然后在其上调用Thread.Join; MSDN 文档中提到了Thread.Join:“阻塞调用线程直到线程终止,同时继续执行标准 COM 和 SendMessage 泵送”(http://msdn.microsoft.com/en-us/library/95hbf2ta.aspx)。但情况似乎并非如此:在调用Thread.Join 之后,表单再次变得无响应,直到线程终止。为什么是这样?我放弃了 Join 的想法,立即从事件处理函数中返回(禁用表单上的按钮以避免用户同时启动多个处理),但随后我遇到了另一个问题:尝试更新进度时开始出现异常栏,运行时抱怨从不是其所有者的线程调用了控件。

所以我最终选择了BackgroundWorker:我在表单中添加了一个,调用它的RunWorkerAsync() 方法并使用ReportProgress() 触发ProgressChanged 事件并在主表单中处理它(以避免交叉-线程控制更新问题)。我终于能够更新进度条了......但现在这是完全异步的:在工作线程调用ReportProgress()(甚至一秒钟!)之后,进度条实际上是在某个随机间隔更新的,这给了一个特别难看的视觉效果。两个例子:

  • 如果我从工作线程调用ReportProgress(),然后调用MessageBox.Show() 以显示有关当前处理步骤的一些消息,我可以看到进度条在 MessageBox 弹出之后前进。李>
  • 我有一个RunWorkerCompleted 事件,它会弹出最后一个带有结果的MessageBox,我可以看到它在屏幕上弹出而进度条仍在填充其最后一步

我在这里错过了什么?

【问题讨论】:

  • 看来,你什么都没错过。消息框是必需的吗?如果去掉,是不是也减少了丑陋?
  • 是的,应用程序逻辑在处理时和结束时都需要它们。当然我可以在里面放一些Thread.Sleep(),但这看起来真的很丑陋……

标签: .net winforms multithreading progress-bar backgroundworker


【解决方案1】:

到目前为止,恕我直言,在 WinForm(和 WPF)应用程序中处理异步的最佳方法是 Reactive Extensions。有点弯路要走,但一旦走上去就回不去了。

【讨论】:

    【解决方案2】:

    添加 Application.DoEvents() 以在需要的地方更新 UI。

    【讨论】:

      【解决方案3】:

      嗯,你已经尝试了很多东西。这里有一些提示,可能不是您的正确答案,但可以帮助您。

      要克服“从其他线程更新控件”问题,您可以在控件上使用InvokeBeingInvoke 命令(为此我使用extension method)。

      除此之外,我认为 Kangkan 的评论是合法的 - 使用 MessageBox 只会给你的问题增加痛苦,因为它是模态的,它会阻止 UI 更新。你确定 MessageBox 是合适的 - 在继续之前你绝对需要用户输入吗?还是您只需要通知他们?如果是后者,您应该考虑使用更像状态栏的东西,或者您在 StackOverflow 上获得的系统消息(想象一下,如果它们都是警报!)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-01-21
        • 1970-01-01
        • 2016-02-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-03
        相关资源
        最近更新 更多