Winforms 为什么我应该从非ui线程调用Control.Invoke?

Winforms 为什么我应该从非ui线程调用Control.Invoke?,winforms,winapi,Winforms,Winapi,为什么我应该从非ui线程调用Control.Invoke?据我所知,任何控制操作都是要控制的信息。因此,当我调用时,例如TextBox.Text=“Text”,它将生成MessageSendMessage(TextBox.Hanlde…)。该消息将排入UI线程消息队列,并由UI线程进行调度。为什么我必须调用invoke,即使它会产生相同的消息?因为您不能直接从创建UI控件的线程以外的线程访问UI控件Control.Invoke将您的调用封送到正确的线程上-允许您从另一个线程调用UI线程,而无需知

为什么我应该从非ui线程调用Control.Invoke?据我所知,任何控制操作都是要控制的信息。因此,当我调用时,例如TextBox.Text=“Text”,它将生成MessageSendMessage(TextBox.Hanlde…)。该消息将排入UI线程消息队列,并由UI线程进行调度。为什么我必须调用invoke,即使它会产生相同的消息?

因为您不能直接从创建UI控件的线程以外的线程访问UI控件
Control.Invoke
将您的调用封送到正确的线程上-允许您从另一个线程调用UI线程,而无需知道UI线程是什么或如何执行封送


更新:要回答您的问题,您不必使用
控件。调用
-如果您有代码将调用封送到正确的线程并将消息发布到消息泵,请使用该命令。然而,这被称为重新发明轮子。除非您正在做一些改变行为的事情。

微软开发人员做出此限制有两个原因:

  • 某些UI函数可以访问线程本地存储(TLS)。从另一个线程调用这些函数会导致TLS操作的错误结果

  • 从同一线程调用所有与UI相关的函数会自动序列化它们,这是线程安全的,不需要同步


  • 从我们的角度来看,我们只需要遵循这些规则。

    我知道如何使用Control.Invoke,我问为什么不能直接调用。无论如何,TextBox.Text会将消息放入UI线程消息队列好的,关于STA activex组件如何,也许有些控件是COM+对象?对不起,我没有理解你的意思。我们正在讨论Windows窗体控件。也许他们中的一些人在内部使用COM,但这不是他们公共接口的一部分。我的意思是,这个限制还保证从STA线程执行UI COM对象。我没有想到COM STA,这是另一个优势(对于Windows窗体开发人员,而不是用户)。