1

I have two different projects and in one, I have a class that defines a custom event to fire under certain conditions:

  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);

Then in another project I create an instance of this class and subscribe to this event:

Guitar.OnButtonPress += Guitar_OnButtonPress;

The event then fires properly, but it seems to be on a different thread, because when I try to access some UI elements, I get an error : The calling thread cannot access this object because a different thread owns it.

The code throwing the error is:

 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))));
                }
}

What can I do to make this run?

Thank you.

Ty Rozak
  • 471
  • 6
  • 19
  • similar problem to this question: http://stackoverflow.com/questions/2403972/c-sharp-events-between-threads-executed-in-their-own-thread-how-to – Justin C Mar 29 '12 at 00:31

3 Answers3

2

You need to check if your event handler is running on a non-UI thread and, if so, invoke it on the UI thread:

How to update the GUI from another thread in C#?

I would like to highlight the less-upvoted answer, which provides a very elegant approach using an extension method. I use this in all of my WinForms projects (and use a variant in WPF/Silverlight projects)

https://stackoverflow.com/a/3588137/141172

Community
  • 1
  • 1
Eric J.
  • 147,927
  • 63
  • 340
  • 553
1

If you are using WinForms this.Invoke(() => GuitarCheck(myargs.State)); (http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx)

If you are using WPF this.Dispatcher.Invoke(() => GuitarCheck(myargs.State)); (http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.invoke.aspx)

Jakub Hromadík
  • 506
  • 2
  • 4
  • 11
0

So you have an event called OnButtonPress whos event handler is obviously executing on a thread that is not hosting VisualTreeHelper. The big question for me is...why? With a name like OnButtonPress it makes me think it should already be on the UI thread. Afterall, it is a button press right? So why is it executing on another thread to begin with?

Using a marshaling operation like Invoke or BeginInvoke is fine as long as you are aware of why it is needed and what it accomplishes for you. But, you really need to take a step back and identify what all is going on that would cause you to need to use a marshaling operation in the first place. There may be a bigger issue here that you need to address.

Brian Gideon
  • 47,849
  • 13
  • 107
  • 150