自定义事件和线程
本文关键字:线程 事件 自定义 | 更新日期: 2023-09-27 18:29:32
我有两个不同的项目,在其中一个项目中,我有一个类定义了在特定条件下激发的自定义事件:
public delegate void ButtonHandler(object myObject,
GuitarArgs myargs);
public event ButtonHandler OnButtonPress;
... other stuff ...
GuitarArgs myArgs = new GuitarArgs( guitarState );
if(OnButtonPress!= null)
OnButtonPress(this, myArgs);
然后在另一个项目中,我创建了这个类的一个实例,并订阅了这个事件:
Guitar.OnButtonPress += Guitar_OnButtonPress;
事件随后正常启动,但它似乎在另一个线程上,因为当我尝试访问某些UI元素时,我会得到一个错误:调用线程无法访问此对象,因为它是由另一个螺纹拥有的。
抛出错误的代码是:
void Guitar_OnButtonPress(object myObject, Guitar.GuitarArgs myargs)
{
GuitarCheck(myargs.State);
}
private void GuitarCheck(GuitarState getState)
{
if (getState.green)
{
VisualTreeHelper.HitTest(guitarCanvas, null,
MyHitTestResult,
new GeometryHitTestParameters(
new RectangleGeometry(new Rect(1, 411, 88, 78))));
}
}
我能做些什么来完成这次跑步?
谢谢。
您需要检查事件处理程序是否在非UI线程上运行,如果是,请在UI线程上调用它:
如何从C#中的另一个线程更新GUI?
我想强调一下投票率较低的答案,它使用扩展方法提供了一种非常优雅的方法。我在所有的WinForms项目中都使用了这个(并在WPF/Silverlight项目中使用了一个变体)
https://stackoverflow.com/a/3588137/141172
如果您使用的是WinFormsthis.Invoke(() => GuitarCheck(myargs.State));
(http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx)
如果您正在使用WPFthis.Dispatcher.Invoke(() => GuitarCheck(myargs.State));
(http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.invoke.aspx)
因此,您有一个名为OnButtonPress
的事件,其事件处理程序显然是在不托管VisualTreeHelper
的线程上执行的。对我来说最大的问题是…为什么?有了像OnButtonPress
这样的名称,我觉得它应该已经在UI线程上了。毕竟,这是一个按钮按下,对吗?那么为什么一开始就在另一个线程上执行呢?
使用像Invoke
或BeginInvoke
这样的封送处理操作是可以的,只要您知道为什么需要它以及它为您实现了什么。但是,您确实需要后退一步,确定导致首先需要使用封送处理操作的原因。这里可能还有一个更大的问题需要解决。