在我的C#Windows窗体应用程序中有两个线程:
当有长时间运行的任务时,它会冻结/停留整个进程并且没有异常或通知被触发..它会挂起应用程序。
仅处理记录的内部应用程序(从SQL表中选择并在Access DB表中插入)
将使用事件操作功能完成UI更新。
查找卡住的流程并行任务的附加快照。似乎线程在内部彼此等待并阻止进程。与SystemEvents.UserPreferenceChanged
事件相关的代码位于其中一个堆栈上。
为什么会发生这种情况,我该如何解决?
答案 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线程已经能够处理任意数量的窗口。