3

可能重复:
为什么 .NET 不允许跨线程操作?
为什么只允许 UI 线程修改 UI?

据我了解,.net 引发非法跨线程调用异常的原因是 GUI 可能会显示不确定的行为。

但是,其他所有对象不都是这种情况吗?如果两个线程在同一个对象上工作,根据代码,该对象可能处于不确定的情况。那么为什么控制元素存在这个例外呢?或者为什么这个例外是控制元素独有的。

以及如何使用调用来提供帮助?它仍然是不确定的。

4

3 回答 3

4

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

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

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

请注意,Invoke这并不保证代表的运行顺序。Invoked如果以正确的顺序执行来自两个不同线程(甚至同一个线程)的两个委托很重要,那么这是一个不同的问题。


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

于 2012-10-16T13:01:06.007 回答
2

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

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

部分原因是 UI 线程可能想要随时重绘它们,因此它们必须随时可用。将其与不希望在等待锁定时延迟 UI 线程相结合,并将其与希望避免甚至无争议的锁定相结合(如果您可以提供帮助,则 UI 线程将不得不取出很多锁)需要为每次访问执行此操作)并且您会得到一个简化的模型,其中更容易说所有访问都必须在 UI 线程上。我确信设计一个没有线程关联的 UI 框架是可能的,但是让它以可预测的方式执行和表现将是棘手的。

于 2012-10-16T12:53:44.197 回答
0

Invoke is used to make sure you are calling the UI on the correct thread. but this is needed for every .net object. The UI is made to work on a single thread(this is true with WPF and Winforms). Two different threads can access the same object as long as its not at the same time. If it this happens it creates a race case and could end in dead lock

于 2012-10-16T12:49:11.903 回答