使用SystemEvents.UserPreferenceChanged和多个UI线程时,UI会冻结

时间:2014-09-22 13:33:09

标签: c# .net winforms ui-thread sta

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

  1. 主线程(Program.cs)
  2. WorkerClass Thread(STA-Apartment)。
  3. 当有长时间运行的任务时,它会冻结/停留整个进程并且没有异常或通知被触发..它会挂起应用程序。

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

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

    查找卡住的流程并行任务的附加快照。似乎线程在内部彼此等待并阻止进程。与SystemEvents.UserPreferenceChanged事件相关的代码位于其中一个堆栈上。

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

    Application Stuck Process

1 个答案:

答案 0 :(得分:3)

SystemEvents.UserPreferenceChanged事件导致死锁。这是一个应用程序与多个线程死锁的Windows的标准方式。调用死锁的最佳方法是按Windows + L键。您可以在this blog post中深入分析此死锁。

SystemEvents类是麻烦制造者,它尝试在程序的UI线程上引发事件。这非常重要,UI不是线程安全的。麻烦的是,您已经有两个创建UI的线程。 SystemEvents无法猜测哪一个是正确的,它只有50%的赔率,因此注定要弄错。如果它最初猜错了程序中的哪个线程是UI线程,并且该线程退出,那么它将是100%错误。

这使得在工作线程上创建UI当然非常危险。从技术上讲,您必须避免使用工具箱中的多个控件。当它在错误的线程上引发时,它们不能很好地处理UserPreferenceChanged事件。 肯定导致死锁的那些是DataGridView,NumericUpDown,DomainUpDown,ToolStrip + MenuStrip和ToolStripItem派生类。那些iffy(不能足够深入地分析代码)的是RichTextBox和ProgressBar。看起来我应该将ProgressBar放在第一组,从你的callstacks判断。

真正的解决方法是在工作线程上创建UI。永远不需要,程序的UI线程已经能够处理任意数量的窗口。

相关问题