简体   繁体   中英

Raise event in one thread to invoke methods in a second thread

I'm working on a program which reacts to events coming from an internet socket, and possibly from timers as well. It seems natural to use two threads:

  • One for the main program
  • A second one which listens to the socket, parses the input, and raises an appropriate event.

Additional requirements:

  1. The application should not rely on a UI thread (it may be run as a console application).
  2. The main program should process messages synchronously, ie in the order in which they arrived.
  3. The main thread must not block on waiting for timers (I guess this means I have to run timers on different threads).

And now for some questions :-):

  1. I'm guessing requirement #1 means that I don't have a built-in message pump, so I can't use Invoke() from the socket listener / timer threads. Is this correct?
  2. How can I safely raise events on one thread (eg the listener), and have the subscribers run synchronously on another (the main thread)?
  3. It is very likely that new events will be raised before the subsequent handler is done. What will happen in this case? Will the event be buffed somewhere by the CLR, or will it be ignored?

And last but not least: I guess I'm aiming for the parallel for the message Producer/Consumer paradigm, but instead of messages, I want to use events. Do you think there is a better approach?

Thanks,

Boaz

EDIT

I want to explain my motivation for using events in the first place. The application is an automated trading engine which has to respond to events that happen in the market (eg a change in the price of a stock). When this happens, there may be multiple subscribers on the main thread which should be invoked, which is a classical scenario to use events.

I guess I can always use the Producer/Consumer with some message queue, and have the consumer raise events on the main thread, but I figured there might be a more direct way.

I think using messages will be the simplest way. If you are using C# 4 this is very easy thanks to the BlockingCollection<>

So have a shared BlockingCollection, where Message is your message class.

Then in your worker thread you do this

var msgEnum = blockingCollection.GetConsumingEnumerable();

//Per thread
foreach( Message message in msgEnum )
{
   //Process messages here
}

That is it.

The GetConsumingEnumerable() will block until there is a message to process. It will then remove the message from the queue and your loop will process it.

What is nice about this is that you can add more threads and in each one you just have the foreach loop.

When you are done call blockingCollection.CompletedAdding();

BTW the queue handles concurrency and will queue messages sent at the same time etc.

Hope this helps

Andre

You could implement a shared queue between your threads. Whenever an event is raised you could push it in the queue. The main thread is an endless loop that checks for new events, removes them from the queue, handles the event and when there are no more events it sleeps for some time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM