自定义事件和线程

本文关键字:线程 事件 自定义 | 更新日期: 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线程上了。毕竟,这是一个按钮按下,对吗?那么为什么一开始就在另一个线程上执行呢?

使用像InvokeBeginInvoke这样的封送处理操作是可以的,只要您知道为什么需要它以及它为您实现了什么。但是,您确实需要后退一步,确定导致首先需要使用封送处理操作的原因。这里可能还有一个更大的问题需要解决。