我有一个带有按钮的窗口,它会触发冗长的处理。我将处理放在一个单独的线程中,但令我惊讶的是,它无论如何都会使 GUI 冻结。没有控件刷新,我什至无法移动窗口。
So 问题是如何启动线程,这样它就不会干扰GUI,即GUI将始终是最新的(在处理时我更改数据,并且GUI显示其中的一些部分)?
这就是我正确启动线程的方式:
var thread = new Thread(doLearn);
thread.IsBackground = true;
thread.Start();
Edit 1
Jon:
- 我根本不使用任何锁
- 没有加入通话
- UI 线程被单独保留——它只是坐在那里
处理是一个带有数学运算的大循环,甚至不分配内存,在 UI 方面,我有与数据绑定(WPF)的控件,例如主循环的当前迭代次数。每次主循环“滴答”时都应该刷新它。循环的计数器是一个属性,每次更改都会触发 OnPropertyChanged(经典 WPF 绑定)。
编辑2——快到了!
好的,乔恩一语中的(谁是惊喜?;-D)——谢谢!问题来自于更改计数器。当我使用本地计数器代替计数器时,GUI 被刷新——我的意思是我可以移动窗口,但是......我看不到计数器的显示。
我这里有一个 WPF GUI,带有这样的数据绑定
<TextBlock Text="{Binding Path=Counter"/>
当然,我有 Counter 属性,每次更改都会发送事件 PropertyChanged。其中一位听众肯定是 GUI。
所以,Jon 的答案是有效的“答案”,但从良好的设计 POV 来看并不完全如此,因为如果 GUI 部分必须提取有关计数器的信息并每(比方说)3 秒更新一次显示,为什么有人会使用数据绑定?对我来说,这种方法使数据绑定的想法无效。
理论上,我可以将 GUI 调度程序传递给处理线程,并在 GUI 线程中完成所有发送,并且它可以工作(我没有尝试),但这意味着非 GUI 部分和 GUI 部分的紧密耦合。
到目前为止,我不知道如何以“正确”的方式做到这一点。到目前为止最好的猜测是创建 TimerDispatcher 但不是在 GUI 端而是在处理库内部,并立即更新 Counter 值,但不时进行所有发送(不过我还没有尝试过)。
小备注:我实际上绑定了更多属性,例如 IsRunning,它在处理开始和结束时更改。这些更改确实会正确影响显示 - 但计数器更改会在 3-4 秒内触发大约 3000 个通知。所以看起来像是干扰问题。我做了另一个测试——我部分地终止了数据绑定,因此发送了通知,但 GUI 没有“接收”它们——而是在监听它们。在这种情况下,GUI 也被冻结。
所以,我仍在听取所有建议——提前感谢您的分享。
Edit 3
故事在这里继续:
如何使用数据绑定进行处理并保持 GUI 刷新? https://stackoverflow.com/questions/4522583/how-to-do-the-processing-and-keep-gui-refreshed-using-databinding