
How do I make event callbacks into my win forms thread safe?当您从表单内订阅对象上的事件时,实际上是在将对回调方法的控制移交给事件源。您不知道该事件源是否会选择在其他线程上触发事件。 问题在于,调用回调时,您不能假定可以在表单上创建更新控件,因为有时如果在与运行表单的线程不同的线程上调用事件回调,则这些控件将引发异常开启。 要稍微简化Simon的代码,可以使用内置的通用Action委托。它节省了您不需要的大量委托类型,从而使您的代码更加实用。此外,在.NET 3.5中,他们向Invoke方法添加了params参数,因此您不必定义临时数组。
以下是要点: 因此,如果您有一个单独的"引擎"线程来做一些工作,并且有一些UI监视状态变化,这些变化可以反映在UI中(例如进度条或其他),那么您就遇到了问题。引擎触发的是一个对象更改事件,该事件已被Form挂钩。但是在引擎的线程上调用了向引擎注册的Form的回调委托。不在窗体的线程上。因此,您无法从该回调中更新任何控件。 h! BeginInvoke进行了救援。只要在所有回调方法中使用此简单的编码模型,就可以确保一切都会好起来:
真的很简单。 这是一种非常紧凑的方法,可以解决此问题并使表单免受多线程事件回调的影响。 在这种情况下,我经常使用匿名方法:
作为 我要做的就是这个。
您可以在函数中内联DoInvoke或将其隐藏在单独的函数中,以为您做脏工作。 请记住,您可以将函数直接传递到DoInvoke方法中。
我对这个话题有些迟了,但是您可能想看看基于事件的异步模式。正确实施后,可以确保始终从UI线程引发事件。 这是一个简短的示例,仅允许一个并发调用;支持多个调用/事件需要更多的工作。
在许多简单的情况下,您可以使用MethodInvoker委托,而无需创建自己的委托类型。 |