当我在UI线程上调用Thread.Sleep时,所有从后台线程调用的方法是否会自动在UI线程的消息泵中排队并在最终唤醒时进行处理?
我遇到了使用大量线程池线程的winform应用程序的问题,有时在锁定/解锁Windows后应用程序挂起。一个猜测是UI线程上发生了一些死锁。另一个是在后台线程上创建一些UI控件。 (这怎么会导致任何问题?)
答案 0 :(得分:1)
规则是,只有创建UI控件的线程才会混乱。这就是为什么有一个“UI线程”的部分原因 - 它让你不必猜测你是否需要Invoke
的东西或只是这样做。 (如果事件发生在UI控件中,它在UI线程中,所以你可以这样做。否则,Invoke
。)所以你想在那个线程中创建你的控件,让它成为那个处理所有用户界面。
您的UI线程有一个目的:处理来自UI的所有事件,以保持您的应用程序响应,并防止其“冻结”。偶尔,它会忙(处理其他事件),但它应该总是处理事件或等待另一个事件。 永远不要在UI线程上调用Thread.Sleep
,除非你有充分的理由,并且可以明确说明为什么这不是一个可怕的想法。几乎任何你想用Thread.Sleep
做的事都可以用计时器来处理,而不是那么摇摇晃晃。
简短版本:是的,如果UI线程正在做某事(甚至是休眠),对Control.Invoke的调用几乎肯定会等到它没有。如果线程正在睡觉,那可能会很长时间。
答案 1 :(得分:1)
是的,解锁工作站时出现死锁是一个非常臭名昭着的Windows窗体线程问题。我从来没有得到很好的诊断,但我很确定它是由SystemEvents类引起的。这是一个程序初始化问题,当控件开始订阅它的事件时,类会按需初始化。
我认为失败模式是在程序主线程以外的线程上创建 first 表单。当你创建自己的启动画面而不是使用.NET屏幕时,你会得到这个。或者启动一个创建自己的表单实例并且过早启动它的线程。因此,SystemEvents将从错误的线程触发其事件。 SystemSwitch事件有点致命。
所以,用细齿梳子查看你的启动代码。在做任何重要事情之前订阅Main()方法中的一个系统事件应该是Q& D修复。