One of the things I've struggled with from time to time is handling
events raised on different threads. For example, an object could be
listening to events from one or more objects running in different
threads besides itself. There is a concern for thread safety. There are
various ways of dealing with this. One way is to make the class thread
safe by putting in locks. But another way is to stream the events from
the various threads into a single thread.
I implemented the ISynchronizeInvoke interface as a delegate queue
class. Basically, clients of this class can call BeginInvoke from
various threads to stream the threads into one. Internally, the delegate
queue is running in its own thread. When BeginInvoke is called, it
enqueues the method and arguments (and a few other items as well) into
the queue and pulses a locked object. From inside the worker thread, the
queue is dequeued, the arguments are retrieved, and the method is
invoked. There are other things going on as well just to ensure that the
ISynchronizeInvoke specification is met.
The way more than one thread can be streamed into one is to have several
objects running in different threads share the same delegate queue.
From the outside, the classes look normal, but when a method call is
made or an event needs to be raised, the delegate representing the
method to invoke is enqueued into the delegate queue. The end result is
that the objects are streaming to the same thread. This would have to be
used with caution for performance reasons, obviously.
Has the ISynchronizeInvoke interface been implemented this way before?
I'm only aware of the Control class's implementation.
Event queues are nothing new. So there's nothing new here in this idea.
I just thought it might be a useful application of the
ISynchronizeInvoke interface. I plan to explore this more to see how
well it works in practise.
I do have a question, though. The Invoke method is suppose to return
synchronously. That's no problem, just have the method wait until the
method is invoked inside the worker thread. However, the documentation
also says that any exceptions thrown from the method invocation are
propagated back to the caller. Hmm, I could do a try/catch in the worker
thread. If an exception is thrown, I could include the exception as an
argument, signal the Invoke method, it would check to see if an
exception has been thrown. If so, it rethrows the exception. But I'm
wondering is there another (better) way?