.net - 控件引发的事件应该在 UI 线程上吗?

标签 .net winforms multithreading events

我知道,当您作为调用者、调用方法或以其他方式操作控件时,您应该调用 UI 线程(或无论如何拥有该控件的线程)来执行此操作。

但是,当控件通过其事件之一回调时,是否可以安全地假设您在正确的线程上被调用?

根据我对常用控件的经验,这始终是正确的,但也许这只是因为大多数事件是用户交互的结果,因此 Windows 消息由 UI 线程上的主消息循环处理。

最近,我自己的自定义控件之一遇到了问题,该控件出于响应用户交互之外的原因调用事件,有时在后台线程上这样做。在一种情况下,该事件的事件处理程序试图操纵另一个控件,该控件生成了非法的跨线程调用异常。

我可以通过检查我的事件处理程序中是否需要调用来解决问题,但我有兴趣知道这里实际上是谁“有错”。

我在任何地方都找不到任何说明有关控件事件的“规则”的文档,甚至找不到任何说明最佳实践的文档。有谁知道吗?或者,您认为应该由控件负责在正确的线程上调用订阅者,还是由订阅者负责检查?

编辑:似乎没有人听说过任何记录在案的约定,但普遍认为在控件所属线程上的 Control 派生类上调用公共(public)事件是个好主意,以避免让消费者感到惊讶。

最佳答案

I know that when you are the caller, calling a method or otherwise manipulating a control, you should invoke the UI thread (or the thread owning that control, anyway) to do so.

嗯...有争议。当然,您永远不应该尝试从托管它的线程之外的线程访问任何 UI 元素。但是,使用像 Invoke 这样的编码(marshal)技术并不总是更新 UI 元素的最佳机制,特别是当您只想使用工作线程中的进度信息更新 UI 时。别弄错我的意思。在某些时间和地点,使用编码(marshal)操作非常有意义,但很多时候让 UI 线程轮询它需要通过 System.Windows.Forms.Timer 更新自身的数据会导致通常更简单、更高效并且同样优雅(如果不是更优雅)的解决方案。

However, when getting called back by a control, via one of its events, is it safe to assume that you're being called on the correct thread?

不一定。我的意思是通常情况下尤其是 Control 实例。但请记住,您也可以将 Component 实例拖放到表单上。其中许多会在其他线程上引发事件。将 BackgroundWorker.DoWorkSerialPort.DataReceived 视为令人​​满意的反例。

I could make the problem go away by checking whether invocation is necessary in my event handler, but I'm interested to know who is actually 'at fault' here.

我不得不说,错在你。如果您的控件确实是 Control 的子类,那么我会非常努力确保所有事件都在 UI 线程上引发。如果您不这样做,那么它肯定会让其他开发人员(无论正确还是错误)认为自己在 UI 线程上感到困惑。如果您的“控件”仅子类 Component 那么您可能没问题,但请确保记录组件的行为。

关于.net - 控件引发的事件应该在 UI 线程上吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10458018/

相关文章:

c# - 通过 Windows 窗体应用程序接受来自 PayPal 的付款

windows - Windows窗体图片框中图片的过渡

c++ - 几个线程 : catching the moment when they all finish work

c# - StringLengthAttribute 和本地化文本

c# - 如何在 Windows 64 位上检测 CPU 速度?

c# - Linux 上的 .NET Core 命名管道问题(地址已被使用)

c# - 如何在 winforms 的 datagridview 中将字符串排序为数字

c# - 如何确定窗体上的哪个控件具有焦点?

multithreading - 为什么这不编译? (RValue 作为线程 CTOR 参数)

java - 多线程排序