使用 SystemEvents.UserPreferenceChanged 和多个 UI 线程时 UI 冻结 [英] UI freezes when using SystemEvents.UserPreferenceChanged and multiple UI threads

查看:33
本文介绍了使用 SystemEvents.UserPreferenceChanged 和多个 UI 线程时 UI 冻结的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 C# Windows 窗体应用程序中有两个线程:

In my C# Windows Forms application there are two threads:

  1. 主线程(Program.cs)
  2. WorkerClass 线程(STA 公寓).

当有长时间运行的任务时,它会冻结/卡住整个进程,并且不会触发任何异常或通知......它会挂起应用程序.

When there is long running Task, it freeze/stuck the entire process and No exception or notification fired..it hangs application.

内部应用程序仅处理记录(从 SQL 表中选择并插入 Access DB 表中)

Internally applications doing processing of records only (selection from SQL tables & inserting in Access DB tables)

UI 更新将使用事件操作功能完成.

UI updates will be done using event Action feature.

为卡住的进程并行任务查找附加的 snap.似乎线程在内部相互等待并阻塞进程.与 SystemEvents.UserPreferenceChanged 事件相关的代码位于其中一个堆栈中.

Find attached snap for stuck process parallel tasks. Seems like threads internally wait for each other and get process blocked. Code related to the SystemEvents.UserPreferenceChanged event is on one of the stacks.

为什么会发生这种情况,我该如何解决?

Why does this happen and how can I resolve it?

推荐答案

它在 SystemEvents.UserPreferenceChanged 事件上死锁.这是具有多个线程死锁的窗口的应用程序的标准方式.调用死锁的最佳方法是按 Windows+L 键.您可以在 这篇博文.

It deadlocks on a SystemEvents.UserPreferenceChanged event. This is the standard way an app with windows on more than one thread deadlocks. Best way to invoke the deadlock is to press the Windows+L key. You can see this deadlock analyzed in depth in this blog post.

SystemEvents 类是这里的麻烦制造者,它试图在程序的 UI 线程上引发事件.这很重要,UI 不是线程安全的.问题是,您有两个 线程来创建 UI.SystemEvents 无法猜测哪个是正确的,它只有 50% 的几率,所以注定会出错.如果它最初猜错了您程序中的哪个线程是 UI 线程,并且该线程退出了,那么它将 100% 错误.

The SystemEvents class is the troublemaker here, it makes an attempt to raise it events on the UI thread of a program. Which is very important, UI isn't thread-safe. Trouble is, you've got two threads that created UI. SystemEvents is incapable of guessing which one is right, it only has 50% odds at it so is doomed to get it wrong. If it initially guessed wrong at which thread in your program is the UI thread, and that thread exited, then it will be 100% wrong.

当然,这使得在工作线程上创建 UI 非常危险.这在技术上是可行的,但是您必须避免使用工具箱中的多个控件.当它在错误的线程上引发时,它们不能很好地处理 UserPreferenceChanged 事件.肯定导致死锁的是DataGridView、NumericUpDown、DomainUpDown、ToolStrip+MenuStrip 和ToolStripItem 派生类.有问题的(无法深入分析代码)是 RichTextBox 和 ProgressBar.看起来我应该把 ProgressBar 放在第一组,从你的调用堆栈来看.

This makes creating UI on a worker thread exceedingly hazardous of course. It is technically possible, you'll however have to avoid using several controls from the toolbox. They don't handle the UserPreferenceChanged event well when it is raised on the wrong thread. The ones that definitely cause deadlock are DataGridView, NumericUpDown, DomainUpDown, ToolStrip+MenuStrip and the ToolStripItem derived classes. The ones that are iffy (can't analyze the code deep enough) are RichTextBox and ProgressBar. Looks like I ought to put ProgressBar in the first set, judging from your callstacks.

真正的治疗方法是不要在工作线程上创建 UI.从来没有必要,您程序的 UI 线程已经能够处理任意数量的窗口.

The true cure is to not create UI on a worker thread. It is never necessary, the UI thread of your program is already capable of handling any number of windows.

这篇关于使用 SystemEvents.UserPreferenceChanged 和多个 UI 线程时 UI 冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆