C# 为什么WPF中的UI控件具有线程关联性?

C# 为什么WPF中的UI控件具有线程关联性?,c#,wpf,C#,Wpf,为什么创建控件的线程是可以更新它的线程?为什么MS没有让人们能够使用锁定和其他线程同步技术来读写多线程UI控件上的属性。每个MSDN的简短描述如下 WPF的线程模型与现有的User32保持同步 具有线程关联的单线程执行的线程模型。这个 其主要原因是互操作性——像OLE 2.0这样的系统, 剪贴板和Internet Explorer都需要单线程 关联(STA)执行 较长的描述如下: WPF中的大多数对象都派生自DispatcherObject,它提供 处理并发和线程的基本构造。WPF是 基于调度器

为什么创建控件的线程是可以更新它的线程?为什么MS没有让人们能够使用锁定和其他线程同步技术来读写多线程UI控件上的属性。

每个MSDN的简短描述如下

WPF的线程模型与现有的User32保持同步 具有线程关联的单线程执行的线程模型。这个 其主要原因是互操作性——像OLE 2.0这样的系统, 剪贴板和Internet Explorer都需要单线程 关联(STA)执行

较长的描述如下:

WPF中的大多数对象都派生自DispatcherObject,它提供 处理并发和线程的基本构造。WPF是 基于调度器实现的消息传递系统。这很有效 很像熟悉的Win32消息泵;事实上,WPF调度器 使用User32消息执行跨线程调用

在讨论时,有两个核心概念需要理解 WPF中的并发性–调度程序和线程关联

在WPF的设计阶段,目标是移动到单个 执行线程,但非线程“亲缘”模型。线 当组件使用执行组件的标识时,会发生关联 线程来存储某种类型的状态。最常见的形式是 使用线程本地存储(TLS)来存储状态。线程亲和力 要求执行的每个逻辑线程只能由一个线程拥有 操作系统中的物理线程,它可以成为内存 密集的最后,WPF的线程模型与 单线程执行的现有User32线程模型 线程亲和力。其主要原因是互操作性—— OLE 2.0、剪贴板和Internet Explorer等系统都需要 单线程关联(STA)执行

假设您有使用STA线程的对象,您需要一种方法 在线程之间进行通信,并验证您是否处于正确的状态 线调度员的角色就在这里。调度员是一名 基本消息调度系统,具有多个优先队列。 消息示例包括原始输入通知(鼠标移动), 框架函数(布局)或用户命令(执行此方法)。 通过从DispatcherObject派生,可以创建具有 STA行为,并将在创建时提供指向调度程序的指针 时间

你可以阅读全文


我个人更喜欢WPF的单线程模型,而不是使用锁定和线程同步技术。可以使用将消息传递到主UI线程,主UI线程负责大多数小型后台进程,如果您需要任何繁重的处理,则仍然可以为此创建自己的后台线程。

WPF与Virtauly all UI Toolkit一样,通过泵送消息循环来工作。由于消息可以在任何时候出现并影响任何控件,因此需要全局锁。为了减少出错的可能性,您可能需要一个在锁下调用委托的函数。也许是这样的:

Dispatcher.Invoke(Delegate, Object())

将其编组到UI线程而不是获取全局锁这一事实只是一个实现细节。

msdn上的MS answer“最后,WPF的线程模型与现有的User32线程模型保持同步,即使用线程关联执行单线程。其主要原因是互操作性——OLE 2.0、剪贴板和Internet Explorer等系统都需要执行单线程关联(STA)。因此,简单的回答是WPF只是建立在旧的遗留东西之上,为开发人员提供了一个闪亮友好的界面。因此是STA模型。只是为了对调度优于锁定/信号量等的偏好进行一些解释。调度器本质上是一个具有单线程消费者(即参与者)的队列。演员们有很多与他们相关的可靠文献。此外,将生产/消费代码与并发代码隔离有助于防止开发人员利用共享状态破坏缓存,这一效果通常会使多线程代码在细粒度并发方面比单线程代码慢得多。