C# 为什么在.net中对控件使用Invoke?

C# 为什么在.net中对控件使用Invoke?,c#,.net,invoke,C#,.net,Invoke,可能重复: 据我所知,.net引发非法跨线程调用异常的原因是GUI可能表现出不确定性行为 但其他物体不是这样吗?如果两个线程在同一个对象上工作(取决于代码),则该对象可能处于不确定的状态。那么,为什么控制元素存在这种异常呢?或者为什么这个异常是控制元素独有的 使用invoke会有什么帮助?它仍然是不确定的 Invoke用于确保在正确的线程上调用UI。但这是每个.net对象都需要的。用户界面在单个线程上工作(WPF和Winforms也是如此)。两个不同的线程可以访问同一个对象,只要它不是同时访

可能重复:

据我所知,.net引发非法跨线程调用异常的原因是GUI可能表现出不确定性行为

但其他物体不是这样吗?如果两个线程在同一个对象上工作(取决于代码),则该对象可能处于不确定的状态。那么,为什么控制元素存在这种异常呢?或者为什么这个异常是控制元素独有的


使用invoke会有什么帮助?它仍然是不确定的

Invoke用于确保在正确的线程上调用UI。但这是每个.net对象都需要的。用户界面在单个线程上工作(WPF和Winforms也是如此)。两个不同的线程可以访问同一个对象,只要它不是同时访问。如果发生这种情况,它将创建一个争用情况,并可能以死锁结束

大多数类型实际上不是线程安全的,但可以从多个线程使用,只要一次只有一个线程使用它们

UI控件并不完全相同:它们具有线程关联性——它们只能安全地在UI线程上使用


部分原因是UI线程可能希望随时重新绘制它们,因此它们必须随时可用。在等待锁定时不想延迟UI线程,如果你能帮助的话,还要避免无争议的锁定(如果UI线程需要对每次访问都执行此操作,那么它将不得不取出大量锁)您可以得到一个简化的模型,在这个模型中,只需说所有访问都必须在UI线程上就可以了。我确信在没有线程关联的情况下设计UI框架是可能的,但要让它以可预测的方式执行和行为将是一件棘手的事情。

Invoke
-ing控件在其他线程上是必需的,因为。要更完整地讨论为什么会存在此限制,您应该阅读该链接-我不打算在这里回答,它只是(但是请确保此限制存在是有充分理由的)

调用
Invoke
对我们有帮助,因为它允许后台线程在UI线程上“做一些事情”——它之所以有效,是因为它不直接调用该方法,而是发送一条消息,上面写着“有机会时运行它”。UI线程正在运行一个连续处理发送到该线程的所有消息的线程,这些消息通常是这样的,在这种情况下,Windows窗体通过在相关控件上引发
单击
事件来处理此消息。在这种情况下,Windows窗体通过运行提供的委托来处理消息

结果是,在任何一个时间点(UI线程),只有一个线程正在修改/使用UI控件

请注意,这并不保证代理的运行顺序。如果从两个不同的线程(甚至同一个线程)调用的两个委托必须以正确的顺序执行,那么这是一个不同的问题



旁白:我们谈论“UI线程”,因为大多数应用程序都有一个线程,所有控件都是在该线程上创建的,但实际上,不同的控件可以创建为线程——它是创建控件并处理消息的线程。显然,为了正确处理这些消息,必须在该线程上运行消息泵。

Invoke-这不仅仅是一个好主意;这是法律。可能的重复不是真正的重复,这两个问题都在问为什么不允许跨线程通信。这个问题是关于Invoke.com的使用,但这确实取决于您的代码。你可以有一个带有对象的竞赛案例。另一方面,您可以让多个线程更改UI,但仍然可以通过创建例如控制锁来确定行为。例如,如果单击了按钮1,则线程2可以添加按钮2。如果单击按钮2,则线程3可能会更改GUI,依此类推。不,不同的线程更改UI将导致异常增益,这不会使其可预测。假设您有一个UI线程和另一个线程,并且两者都试图更改UI。“其他线程”消息可能在UI线程更改之前或之后出现,从而导致不可指示性。@user1316459这不是
Invoke
试图解决的问题-
Invoke
存在,因为在Windows窗体中明确禁止跨线程UI调用(有关原因的讨论,请参阅我回答中的第一个链接)。如果UI线程操作在另一个线程之前/之后很重要,那么这是一个完全不同的问题-
Invoke
不保证消息的处理顺序。首先,这不是完全不允许的。您只需将Control.checkforillegalcrossthreadcalls设置为false。但如果我没有像许多人鼓励的那样将其设置为false,我就必须使用invoke。我的观点是,这并不能让事情变得更好。“我的UI将具有相同的可预测性状态。@user1316459“无跨线程UI调用”规则保护控件的内部状态比使多线程可预测更重要。例如,如果一个
ListView
在向其
Items
集合添加一个项和将该项添加到底层本机控件之间被中断,那么可能会发生各种不好的事情。编写一个没有这些限制的UI框架并非不可能,但非常困难。