【问题标题】:WPF user interface with long processing execution hangs具有长时间处理执行的 WPF 用户界面挂起
【发布时间】:2011-12-23 16:55:14
【问题描述】:

对于这篇长篇文章,我感到非常抱歉。我需要一些关于 c# wpf 问题的帮助。我已经构建了一个复杂的用户界面(不知何故),并且有一些按钮......比如开始和停止等等。

当我单击开始按钮时,执行过程开始于与某些协议层和其他协议层进行通信,这是一个漫长的过程.. 在此过程中,我必须显示一些通知 UI,例如“输入文本”、“选择某些东西” " 等等......这次我必须显示一些 wpf 窗口对象......一段时间后我必须自动销毁窗口并再次进行处理。

起初我尝试在主窗口类中运行执行。但它导致当执行开始时.. 用户无法单击任何内容并且 ui 没有响应而只是挂起。我调查了这个问题……发现 UI 正忙于协议层执行中的处理,所以它没有响应。

这是我的问题...你能给我一些解决方案吗...

  1. 我将有 2 个按钮..启动和停止
  2. 当我单击开始按钮时...将在名为 Processor 的函数中启动一个大进程(如嵌套的 for 循环,其中包含一个大 int,将持续 50 秒)。
  3. 在处理函数时,处理器将创建几个窗口并显示它们等待 5-10 秒,然后将它们销毁。或用户点击窗口上的;s
  4. 并且在整个过程中,停止按钮都应该是可点击的,这样当我点击停止按钮时.. 进程应该停止。

我在后台工作程序、调度程序...并使用单独的线程进行了尝试。但没有运气。我想我错过了一些东西。因为如果我等待一些结果显示一个窗口..窗口肯定会挂起..如果我用不同的线程将它们分开..它不会相互通信。请给我一些建议

【问题讨论】:

  • Dispatcher 可能仍然会锁定 UI,如果它是 CPU 密集型的,但是 BackgroundWorker 应该可以正常工作。您能否向我们展示您尝试使用 BackgroundWorker 的代码?

标签: wpf multithreading process background dispatcher


【解决方案1】:

Dispatcher 绝对是解决方案。您可能需要设置Dispatcher Priority。分享一些相关代码也可能会暴露一些问题。

【讨论】:

  • Dispatcher 仍然使用主 UI 线程,并可能导致它在 CPU 密集型操作期间锁定。
  • @Rachel - 这就是为什么我建议应该使用线程优先级来分配哪个线程应该具有哪个优先级(UI vs Worker)。
  • @SilverNinja 我已经让它锁定了 UI,即使使用不同的 DispatcherPriority。在我放弃并切换到使用后台线程之前,我以尽可能低的优先级(SystemIdle)进行了测试。不过,这是针对 CPU 密集型操作,而不是等待回复的数据库调用。
  • @Rachel - 很高兴知道。我通常将 CPU 密集型操作卸载到另一个系统(数据库、服务调用等)并且从未见过您遇到过这种锁定。
  • 抱歉回复晚了。在处理器功能中,我使用 AutoResetEvent 和 Timer。我每 200 毫秒检查一次协议层的响应。因此,当我通常使用调度程序/后台工作程序启动进程时,它通常会挂起,因为处理器功能正在等待并使用计时器进行检查
【解决方案2】:

BackgroundWorker 应该做你需要的。将 WorkerSupportsCancellation 和 WorkerReportsProgress 设置为 true。

我不建议弹出多个窗口。弹出一个窗口以显示状态。在 DoWork 的循环中,调用 BackgroundWorker.ReportProgress。然后在 ProgressChanged 事件处理程序中,更新窗口的状态。

要实现停止: 在您的 DoWork 方法中,您需要检查循环中 BackgroundWorker 的 CancellationPending 属性。当它为真时,您需要退出该方法。点击停止按钮,调用 BackgroundWorker.CancelAsync()。

【讨论】:

  • 是的,它有效。但是当我试图在函数reportProgress中创建一个新的wpf窗口实例时......它总是显示InvalidOperation异常......“调用线程必须是STA,因为许多UI组件都需要这个。”你可以提出任何建议,以便我可以创建一个窗口实例并在其中显示它...... backgroundworker 进程。当用户单击取消按钮时,我将销毁它。
  • 现在我可以在后台工作程序中运行一个进程,并且可以在执行这个进程时更新一个文本框。但主要问题是我无法在该后台工作人员中创建另一个 wpf 窗口的新实例。我在stackoverflow中搜索过,发现这是不可能的(!)。 back..worker 使用 MTA 线程,在创建新窗口时需要 STA 线程。请提出一些方法
  • 这里有一篇详细的文章和一个例子:msdn.microsoft.com/en-us/library/… 你不应该在 DoWork 事件处理程序中修改 UI。而是在 ProgressChanged 或 RunWorkerCompleted 中更新 UI。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-28
  • 2017-12-08
  • 1970-01-01
  • 1970-01-01
  • 2016-01-19
相关资源
最近更新 更多