我知道如果我从不同的线程修改一个控件,需要小心,因为WinForms和WPF不允许从其他线程修改控件的状态。
为什么有这个限制?
如果我能编写线程安全的代码,我应该能够安全地修改控件状态。那么为什么还要存在这个限制呢?
我知道如果我从不同的线程修改一个控件,需要小心,因为WinForms和WPF不允许从其他线程修改控件的状态。
为什么有这个限制?
如果我能编写线程安全的代码,我应该能够安全地修改控件状态。那么为什么还要存在这个限制呢?
许多GUI框架都有这个限制。根据书籍《Java并发实践》的介绍,这是为了避免复杂的锁定问题。问题在于GUI控件可能需要对UI事件、数据绑定等做出反应,这会导致来自多个不同源头的锁定,从而增加死锁的风险。为了避免这种情况,.NET WinForms(以及其他UI)限制对组件的访问仅限于单个线程,从而避免锁定。
Control.CheckForIllegalCrossThreadCalls
强制实施这一点。 - Michael Petrotta.NET保留在您创建控件的线程中随时访问它的权利。因此,来自另一个线程的访问永远不会是线程安全的。
Windows支持许多操作,尤其是在组合使用时,本质上不是线程安全的。例如,当一个线程试图将一些文本插入以第50个字符开头的文本字段时,同时另一个线程试图从该字段删除前40个字符,那么应该发生什么?Windows可以使用锁定来确保第二个操作无法开始,直到第一个操作完成,但是使用锁定会增加每个操作的开销,并且还可能导致死锁,如果对一个实体的操作需要操作另一个实体。要求涉及特定窗口的操作必须在特定线程上进行比防止同时执行不安全操作更严格的要求,但相对容易分析。在多个线程中使用控件并通过其他方式避免冲突通常更加困难。
实际上,据我所知,这就是最初的计划!每个控件都可以从任何线程访问!只有当另一个线程需要访问控件时才需要线程锁定,而且由于锁定很昂贵,因此创建了一种新的线程模型称为“线程租赁”。在该模型中,相关控件将被聚合到“上下文”中,仅使用一个线程,从而减少所需的锁定量。相当酷,不是吗?
不幸的是,这种尝试过于大胆,无法成功(并且稍微复杂,因为仍然需要锁定),因此在wPF中再次使用了老式的Windows Forms线程模型--单个UI线程和创建线程来声明对控件的所有权--使我们的生活更加轻松?
Application.Run
时,线程会运行消息循环,这可以在多个线程上完成。 - Ben Voigt