.NET UI元素线程限制的原因

时间:2010-06-01 23:47:43

标签: .net user-interface multithreading

我们知道不可能从除了实例化元素的线程之外的任何线程执行操作任何UI元素属性的代码...我的问题是:为什么?

我记得当我们使用COM用户界面元素时(在COM / Visual Basic 6.0天内),所有UI元素都是使用COM类和共同类创建的,这些类使用称为Thread的内存模型来存储其资源。本地存储(TLS),但我记得,这是必需的,因为与构建COM组件的方式有关,并且不应与.NET UI元素相关。这种限制仍然存在的根本原因是什么?

是否因为底层操作系统仍然对所有UI元素使用基于COM的Win32 API类,甚至是在托管.NET应用程序中操作的那些元素?

3 个答案:

答案 0 :(得分:2)

AFAIK,它比COM更基本。它直接用于良好的Windows API。我相信Windows中的Windows预计将由一个线程所拥有。每个线程都有自己的消息泵,将消息分派给它拥有的窗口。这是Windows的一个非常基本的构造 - 这些天可能有点陈旧,但基本。

我的感觉是,当您需要将WPF集成到Windows窗体应用程序中时,或者如果您需要使用您在某处获得的HWND在应用程序中的其他位置使用Windows对象时,此线程关联有助于实现互操作性。它可能也是允许旧版Windows(XP)托管WPF应用程序而不对操作系统本身进行任何重大架构更改的原因。

答案 1 :(得分:1)

听起来你指的是WPF而不是通用的Windows API编程。我不是WPF内部的专家,但是这里有一些关于为什么在一个UI线程中保持UI操作是个好主意的项目:

  1. 避免死锁。当你有多个线程运行时,所有共享资源都必须受到某种锁的保护。当存在多个锁时,存在陷入死锁的高风险 - 线程A拥有锁1但是在锁2上等待,线程B拥有锁2但是正在等待锁1.这可以通过严格的顺序来避免锁定获取,但人性不足。
  2. 减少对昂贵锁具的需求。如果您可以要求所有UI操作在UI线程上执行,则可以消除保护内部数据所需的大量锁定。
  3. 降低创建没有消息循环的线程所拥有的窗口句柄的风险。
  4. 最后一项与Win API相关。创建窗口句柄时,它将绑定到发出CreateWindow调用的线程。发送到该窗口句柄的消息将放置在与该线程关联的消息队列中。如果该线程不处理窗口消息,则窗口将无响应 - UI冻结。如果另一个线程尝试SendMessage到该窗口,该线程也将被冻结,等待同步调用完成。这种雪球很快就会变成丑陋的。这就是为什么确保只在准备处理窗口消息的线程上创建窗口句柄的重要性。

    为什么窗口句柄的消息队列绑定到特定线程?我不知道,但我确定答案并非微不足道。

答案 2 :(得分:0)

来自http://msdn.microsoft.com/en-us/library/ms741870.aspx

  

历史上,Windows允许使用UI   只能由。访问的元素   创建它们的线程。这意味着   一个背景线程负责   一些长时间运行的任务无法更新   文本框完成后。视窗   这样做是为了确保完整性   UI组件。列表框可以看   如果其内容已更新,则很奇怪   由背景线程期间   画。