2010-09-23 63 views
2

当我在UI线程上调用Thread.Sleep时,后台线程中的所有调用方法是否会自动排队到UI线程的消息泵中并在最终唤醒时进行处理?当UI线程正在休眠时,可以无限期地从后台线程块中调用方法吗?

我遇到了使用大量线程池线程的Winform应用程序的问题,有时在锁定/解锁Windows之后应用程序挂起。一个猜测是在UI线程上发生了一些死锁。另一个是一些UI控件是在后台线程上创建的。 (这怎么会导致任何问题???)

回答

1

规则是,只有创建一个UI控件的线程应该弄乱它。这就是“UI线程”的原因之一 - 它让你无需猜测你是否需要Invoke的东西或只是做。 (如果事件发生在UI控件中,它在UI线程中,所以你可以这样做,否则,Invoke。)所以你想在那个线程中创建你的控件,并让它成为处理所有UI的控件正如它打算的那样。

您的用户界面线程有一个目的:处理来自用户界面的所有事件,以保持您的应用程序响应,并防止它看起来“冻结”。偶尔,它会很忙(处理其他事件),但它应该总是处理事件或等待另一个事件。 千万不要在UI线程上调用Thread.Sleep,除非你有一个很好的理由,并可以明确说明为什么它不是一个可怕的想法。几乎所有你想用Thread.Sleep做的事情都可以用定时器来处理,而不是那么摇摇晃晃。

短版:是的,如果UI线程正在做某事(甚至是睡眠),对Control.Invoke的调用几乎肯定会等到它不是。如果线程正在睡觉,那可能会很长时间。

1

是的,解锁工作站时发生死锁是一个相当臭名昭着的Windows窗体线程问题。我从来没有得到一个很好的诊断,但我确信它是由SystemEvents类造成的。这是一个程序初始化问题,当控件开始订阅它的事件时,类会根据需要进行初始化。

我认为失败模式是创建第一个形式在一个线程以外的程序的主线程。例如,当你创建自己的启动画面而不是使用.NET启动画面时,你会得到这个。或者旋转一个创建自己的表单实例的线程,并尽快启动它。结果,SystemEvents将从错误的线程中激发它的事件。 SystemSwitch事件以某种方式致命。

所以,用细齿梳看看你的启动代码。在做任何重要的事情之前,订阅Main()方法中的一个系统事件应该是Q & D修复。

相关问题