I have been using multiple threads a bit of late. I am using VS C#2003 at present - but may upgrade to 2005, especially if it helps solve this problem!
Here goes:
Class1 has a slow process going on in a thread. It Has a public event which fires to say how many percent are complete. It also has one to fire with included data when it finishes.
Class2 is another slow process with its own thread. It subscribes to Class1_Finished. It also has its own Finished_Event.
Form1 Subscribes to all the above events.
To my way of thinking, to reduce the overhead of coding we should be able to make it so that the FireXXXXEvent() checks to see if each thing subscribed is on the same thread. If it is not, it does a BeginInvoke(), oherwise it just runs it.
That way each thing that subscribes to and event does not have to check to see what thread it is on. This surely would be the case if I wrapped it as a component. Then everytime a user of a component subscribes to and event they would have to see if it is on the same thread.
So How do I make events fire on the same thread as the thread the subscriber is on
Cheers all!
Mark

Threading and events . with forms and other threads.
Arshnet
If you can change to 2.0 framework (VS2005), then the
System.Threading.SynchronizationContext
is your friend. Makes life much simpler.
Adam Magee
Brett Woods
Just to make sure we're on the same page let me clarify something. Threads and events are independent of each other. You can raise events on any thread and handle events on any thread. Unless you are attempting to interact with the UI or with thread-specific data the thread that an event occurs on is irrelevant. If you are dealing with multiple threads then you need to be sure to use synchronization for accessing any shared resources but otherwise it doesn't matter. I follow the logical concept that every event is raised on an arbitrary thread. This is not how it actually works but this line of reasoning prevents me from making any assumptions about the thread an event will be raised on.
In your case you can have any number of objects on any number of threads listen for the events raised by your CommsData class. For example you may have a logger class that logs all data to a file running on one thread. Additionally you may want to update your UI with the progress on a different thread. The issue here is that your logger and UI components may be called on an arbitrary thread. Therefore your logger component must use sync objects to ensure that it isn't invoked on two separate threads at the same time to avoid garbling the output. For your UI component it is mandatory that you interact with it through the thread that created the UI component (the main thread normally). Therefore you must use the Invoke/BeginInvoke trick. Using the InvokeRequired property permits you to skip the overhead if you are already running on the appropriate thread.
It would be more time consuming for your CommsData class to determine which thread each handler was created on in order to switch contexts. Furthermore you are assuming that the thread that created and/or added the handler is the right thread to begin with. The reason this is more time consuming is because your class would need to switch contexts or at least send some sort of thread notification to each handler's thread. But in the general case most handlers could care less what thread the event comes in on. It would be a waste. Especially since you are dealing with a serial port time is of the essence so you'll want to dispatch the event as soon as possible. In fact I'd even go so far as to recommend that your comm class actually queues the request to a separate thread for dispatching just to avoid the case of an event handler taking too long to respond and therefore you losing data on the serial port.
I'm a little confused about your scenario. Given what you said it appears that the CommsData class listens on the serial port. When data comes in it raises an event. The UI handles the event and then calls ProcessData to do some processing. ProcessData raises a progress event to the UI. Given this scenario I'd say the only time you care about the threading is when ProcessData sends a progress event. I assume this is the only time the UI is actually involved. When CommsData raises an event the UI component might call ProcessData but unless it actually updates the UI (it might) then the thread is unimportant. It can simply call ProcessData and return. However this begs the question of whether you actually want multiple copies of ProcessData running at all. If you do then each time the UI gets an event it creates a new instance of the ProcessData class. Otherwise it'll have to sync with the existing ProcessData instance.
I don't understand all of your requirements but my initial thought would be to create a CommsData and ProcessData instance in your UI during initialization. I would then have ProcessData listen for the CommsData event directly. It then does its processing. The UI would then only listen for the ProcessData event and would make the transition to the UI thread (if needed) to handle it. In this case only the UI event handler would need to use the Invoke stuff. ProcessData can handle the event on any thread (using proper sync objects for shared resources).
Hope this clarifies some things.
Michael Taylor - 1/23/06
Vicki Maxon
OK, Thats a good start. But it really seems silly that every time I subscribe to an event that I have to see if it is on the same thread. Forgetting Windows.Forms.....(well including it as you say......
I am buiding a part to monitor and process external comms data (say serial port for example).
Class CommsData
It has an event everytime data is received.
It runs its own thread all the time to monitor the comms port.
Class ProcessData
It has an event to say data is processed.
It has an event to say what percent of processing is complete
A windows Form
This creates and subscribes to both lower classes.
When comms is recieved, it starts the processing going.
However, you may also want the processing to subscribe to the CommsData_ready event. Now how do you wire that, or does it all have to go through the main thread
Ie you can NEVER have one thread subscribe to another threads events
alivali
You don't. This would be counterintuitive to how .NET and the standard controls work. You can isolate the code to a simple routine but only the subscriber knows what thread they are running on. The standard solution is to use the following code in the handler for your events inside the form. Of course you can actually nest this code inside some method or property within the form.
void SomeEventHandler ( args )
{
if (InvokeRequired)
Invoke(new myDelegate(method), args);
else
method(args);
}
Inside your threads that raise events you simply do:
void RaiseEvent ( args )
{
EventHandler hdlr = myEvent;
if (hdlr != null)
hdlr(this, args);
}
What happens is that the event is raised on the thread that calls RaiseEvent. The handler checks to see if it is on the UI thread. If it is then it simply invokes the appropriate method to do the work. If not then it passes the request on to the UI thread where it will invoke the method. Of course if you want it to be asynchronous then you can use BeginInvoke instead but in my experience it gains you little.
As a side note many times it is better to have method and SomeEventHandler be the same. This reduces the amount of code you have to write. You would do this by ensuring that SomeEventHandler has the same signature as method. The call to method in the else-clause then changes to the code you want to execute. This reduces the overhead by a function call.
void TitleChanged ( object sender, EventArgs e )
{
if (InvokeRequired)
Invoke(new EventHandler(TitleChanged), new object[] { sender, e });
else
//Do whatever
}
The nice thing about this is that the same method handles requests on any thread. I'll warn you against automatically applying this to all your public members as controls/components are by default not thread aware. Unless the threading is internal to your control then your clients are probably already dealing with this issue for other controls and therefore would be doing the same for your control/component. It would be redundant. Just a suggestion. Of course for internal components then do whatever is easiest.
As another aside I would avoid asynchronous event invocations for a couple of reasons. Firstly your events may arrive out of order. For example suppose you raise an event whenever some text changes. With an async request if the text changes from "A" to "B" and then from "B" to "C" there is no guarantee that the async event raised for "A" to "B" will arrive before the event for "B" to "C" therefore this could cause you some problems. Secondly the underlying event handler may go away before the event is raised causing an exception. Technically this is possible in sync events but it is unlikely. Finally async events require additional code to clean up the request when it completes. In general you should assume that event handlers are fast. It is the responsibility of the handler to decide whether they need to asynchronously handle the event themselves.
IMHO,
Michael Taylor - 1/23/06
Michael Taylor - 1/23/06
No FREE
http://www.lowendahl.net/content.aspx cshrpContent=csa31