I'd like to have two Threads. Let's call them :
- Thread A
- Thread B
Thread A fires an event and thread B listen to this event. When the Thread B Event Listener is executed, it's executed with the Thread A's thread ID, so i guess it is executed within the Thread A.
What I'd like to do is be able to fire event to Thread B saying something like: "hey, a data is ready for you, you can deal with it now". This event must be executed in its own Thread because it uses things that only him can access (like UI controls).
How can I do that ?
Thank you for you help.
I have only been using C# for a few weeks now but I encountered the same question of how to fire events across threads. There is not a lot of complete examples available (any?) and it was difficult to understand all of the individual pieces from various experts. After some time I finally developed something that works, so I wanted to share a complete example of it on this thread for any newcomers like myself. Also I welcome any expert advice or criticism as I am quite new to C# and surely this can be improved.
This is a complete example minus a small form with 3 buttons and a vertical trackbar, all with default names. Make the form in Designer and overwrite it with the TestEvent class I have, then hook up the 3 buttons OnClick events. The trackbar can be used to select the thread which you want to fire an event to via the buttons, and will automatically scale when you change numThreads in void Main(). Button2 will send an event to shutdown the thread.
The MyEvent class can be used in conjunction with any class implementing the IMyEventActions interface. The class using MyEvent will automatically receive fired events into OnSomethingHappened(...). In addition, the class instantiating MyEvent can subscribe to other classes events recursively. Firing events is easily achieved through the MyEvent.Fire(...) Method.
The easiest way is probably to subscribe using an event handler which just marshal the "real" handler call onto thread B. For instance, the handler could call
Control.BeginInvoke
to do some work on thread B:If you're using Windows Forms or WPF, and do not have a Control reference handy from your event handlers, you could also capture the reference of System.Threading.SynchronizationContext.Current in something running on the UI thread, and expose that reference to your event handlers.
Then, when you need to have something run on the UI thread, invoke Post() or Send() on the captured SynchronizationContext reference from your event handler, depending on whether you want it to be run asynchronously or synchronously.
Basically this is just sugar around capturing a Control reference and calling Invoke() on it, but can make your code simpler.
You'll need to marshal the information back into the UI thread.
Typically, you would handle this in your Event handler. For example, say Thread A was your UI thread - when it subscribed to an event on an object in Thread B, the event handler will be run inside Thread B. However, it can then just marshal this back into the UI thread: