c# - 如何启动一个线程来保持GUI刷新?

标签 c# wpf multithreading

我有一个带有按钮的窗口,它会触发冗长的处理。我将处理放在一个单独的线程中,但令我惊讶的是,它无论如何都会使 GUI 卡住。没有控件刷新,我什至无法移动窗口。

所以问题是如何启动线程,这样它就不会干扰GUI,即GUI将始终是最新的(在处理时我更改数据,并且GUI显示它的一些片段)?

这就是我正确启动线程的方法:

        var thread = new Thread(doLearn);
        thread.IsBackground = true;
        thread.Start();

编辑 1

乔恩:

  1. 我根本不使用任何锁
  2. 不加入通话
  3. UI 线程保持独立 - 它只是坐在那里

处理是一个带有数学运算的大循环,甚至没有分配内存,在 UI 方面,我有与数据绑定(bind)(WPF)的控件,例如主循环的当前迭代次数。每次主循环“滴答”时都应该刷新它。循环的计数器是一个属性,每次更改都会触发 OnPropertyChanged(经典 WPF 绑定(bind))。

编辑 2——快完成了!

好的,乔恩一语中的(谁是惊喜?;-D)——谢谢!问题来自于更改计数器。当我使用本地计数器代替计数器时,GUI 被刷新——我的意思是我可以移动窗口,但是......我看不到计数器的显示。

我这里有一个 WPF GUI,具有这样的数据绑定(bind)

<TextBlock Text="{Binding Path=Counter"/>

当然,我有 Counter 属性,每次更改都会发送事件 PropertyChanged。其中一个监听器肯定是 GUI。

所以,Jon 的答案是有效的“答案”,但从良好的设计 POV 来看并不完全是这样,因为如果 GUI 部分必须提取有关计数器的信息并每(比方说)3 秒更新一次显示,为什么有人会使用数据绑定(bind)?对我来说,这种方法使数据绑定(bind)的想法无效。

理论上,我可以将 GUI 调度程序传递给处理线程,并在 GUI 线程中完成所有发送,并且它可以工作(我没有尝试),但这意味着非 GUI 部分和GUI部分。

到目前为止,我不知道如何“正确”地做到这一点。到目前为止最好的猜测是创建 TimerDispatcher 但不是在 GUI 端而是在处理库内部,并立即更新 Counter 值但不时执行所有发送(不过我还没有尝试过)。

小备注:我实际上绑定(bind)了更多属性,例如 IsRunning,它在处理开始和结束时更改。这些更改确实会正确影响显示 - 但计数器更改会在 3-4 秒内触发大约 3000 个通知。所以看起来像是干扰问题。我做了另一个测试——我部分地终止了数据绑定(bind),因此发送了通知,但 GUI 没有“接收”它们——而是在监听它们。在这种情况下,GUI 也被卡住。

所以,我仍在听取所有建议——提前感谢您的分享。

编辑3

故事在这里继续:

How to do the processing and keep GUI refreshed using databinding?

最佳答案

照现在的样子应该没问题。可能会卡住您的用户界面的事情:

  • 您是否在 UI 线程中锁定,并在其他线程中锁定同一个锁?
  • 您是否从 UI 线程中调用线程上的 Join
  • 您是否在 UI 线程中执行一些其他繁重工作?

如果您能想出一个简短但完整的程序来显示问题,我相信我们可以帮助解决它......但它肯定应该没问题。

编辑:好的,现在您已经添加了以下内容:

The counter of the loop is a property which triggers OnPropertyChanged with each change (classic WPF binding).

所以您要从非 UI 线程更新属性?我预计这会导致问题,因为它会从错误的线程触发 UI 更改。

我建议您采取以下方法:

  • 通过 Dispatcher.BeginInvoke 定期更新计数器
  • 拥有“UI 计数器”和“工作计数器” - 并通过 DispatcherTimer 将值从“工作计数器”复制到 UI 线程中的“UI 计数器”,本质上是轮询它.

关于c# - 如何启动一个线程来保持GUI刷新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4497115/

相关文章:

java - Apache POI 在多线程中的 tmp 目录上获取 java.io.IOException

c# - 根据 Razor MVC 4 中的条件从 Controller 控制局部 View

c# - 使用 LumiSoft - C# 从 Gmail 收件箱获取邮件

c# - 如何查看 silverlight 项目中部分类的其余部分?

c# - 位置 C# 位置文本

c# - 带有 2 个表的 WPF TreeView(分层数据模板)

wpf - 如何在WPF中将鼠标悬停时更改图像?

c# - WPF MVVM 本地化 C#、运行时

python - kivy 使用线程和 matplotlib 运行 python 代码

c# - 从 BackgroundWorker 启动时计时器是否工作?