我有两个不同的项目,在一个中,我有一个类定义了在某些条件下触发的自定义事件:
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))));
}
}
我该怎样做才能让这次运行?
谢谢。
答案 0 :(得分:2)
您需要检查您的事件处理程序是否在非UI线程上运行,如果是,请在UI线程上调用它:
How to update the GUI from another thread in C#?
我想强调一下不太好的回答,它提供了一种使用扩展方法的非常优雅的方法。我在所有WinForms项目中使用它(并在WPF / Silverlight项目中使用变体)
答案 1 :(得分:1)
如果您使用的是WinForms
this.Invoke(() => GuitarCheck(myargs.State));
(http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx)
如果您使用的是WPF
this.Dispatcher.Invoke(() => GuitarCheck(myargs.State));
(http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.invoke.aspx)
答案 2 :(得分:0)
因此,您有一个名为OnButtonPress
的事件,事件处理程序显然正在未托管VisualTreeHelper
的线程上执行。对我来说最大的问题是......为什么?使用类似OnButtonPress
的名称,它让我觉得它应该已经在UI线程上了。毕竟,这是一个按钮按下吗?那么为什么它是在另一个线程上执行的?
使用像Invoke
或BeginInvoke
之类的编组操作是很好的,只要您知道为什么需要它以及它为您完成的任务。但是,你真的需要退后一步,确定一切都会导致你需要首先使用编组操作。这里可能存在一个更大的问题需要解决。