2

I’m developing a module that has to handle many events coming from an external system. I’ve to use a third party class providing an event (OnNewMessage) passing some parameters as input and two as output, each event require a bunch of time in order to be processed. I’d like to serve these events in a parallel way, in order to avoid blocking the caller and to process multiple request in parallel.

Here an example of my code:

void Init()
{
   provider.OnNewMessage += new OnMessageEventHandler(processEvent);
}

void processEvent(string xml, int …, out string resultXML, out string description)
{
   ...
}

Which is the best approach to do this in C# 3.5?

Thanks

Kill KRT
  • 1,101
  • 2
  • 17
  • 37

2 Answers2

5

I would use a queue to store the events, and then consume that queue from a bounch of thread from the thread pool.

Felice Pollano
  • 32,832
  • 9
  • 75
  • 115
  • agree, use a queue could avoid blocking the caller. – Peter Long Jun 23 '11 at 12:08
  • Could use the System.Collections.Concurrent.ConcurrentQueue – Martin Ingvar Kofoed Jensen Jun 23 '11 at 12:09
  • +1 for the queue. http://msdn.microsoft.com/en-us/library/kbf0f1ct.aspx -- ThreadPool.QueueUserWorkItem – ba__friend Jun 23 '11 at 12:10
  • @Martin Ingvar Kofoed Jensen, he asked for .NET 3.5 – ba__friend Jun 23 '11 at 12:13
  • Please, could you provide an example? I'm not sure to have understand your solution. When I serve an event I've to compute its output before to leave the event-handler. So... How can I queue the event, serving in another thread, and leave the method without having yet the value for output parameter? Oh my... I can even ubderstand my question? :-) – Kill KRT Jun 23 '11 at 12:26
  • @Kill KRT create a class t encapsulate the arguments of the current handler, craete a Queue and feed it. Use a lock to avoid concurrency issues. – Felice Pollano Jun 23 '11 at 12:35
  • @Felice Pollano Be patient... I'm not a multithreading ninja ;-) How I can put event in that queue? I cannot only queue arguments in the "processEvent", because before I leave that method I must assign a result to the output parameter... Feel a little confused! Could you provide please a link to an example or documentation? Thanks! – Kill KRT Jun 23 '11 at 13:26
  • 2
    You seem to want to both have your cake and eat it . You say that the event caller must not block but, at the same time, cannot exit before its output parameters are loaded. I can't see how you can have both! – Martin James Jun 23 '11 at 14:02
  • 1
    Kill KRT: Oh.. I think I have it now. You want a caller to wait/block until the output parameters are loaded, but without waiting/blocking *other* callers who are requesting work. Is that it? If so, you can do it by creating an event in the class instance that gets queued up with the input/output parameters, then queue the object and wait on the event. When some thread done the work and loaded the results into the object, it signals the event. Your event handler can then load the output parameters from the object and exit. – Martin James Jun 23 '11 at 14:11
  • @Martin James: Yes, the event is risen continuosly and I've to avoid to block the caller, it doesn't matter how much time it takes to compute the output, it is just important not to block the caller! The solution you and @FelicePollano propose it is not really clear to me. :-/ I didn't understand how I can queue the event and avoid to block the caller. Could you provide a simple example? Thanks. – Kill KRT Jun 23 '11 at 16:48
  • Unless the task of generating the resultXML etc. can be internally split up, any caller will have to wait inside processEvent until the whole job is done. If the task is done by the calling thread, the processEvent will not return until the task is done. If the task is queued off to a threadPool and the caller blocks on an event, the processEvent will still not return until the task is done. Either way, a calling thread will just have to wait in the processEvent. I can't see any difference from the caller POV, except that the threaded approach can service multiple calling threads in parallel. – Martin James Jun 24 '11 at 11:35
  • @MartinJames: Please could you write an example that applies to my question code? It is not clear to me where I've to queue the method and where/how to launch the "computing" thread. Really sorry, I didn't understand (it's my problem, I know! ;-)) your solution. Many thanks! – Kill KRT Jun 26 '11 at 14:04
-2

Here is the modified answer:

you don't want to block the caller , and you also want the caller to wait for the output. Then I think what you need is a web service. You define a web service for the task. And the caller call the web service to get the result. Web services support parallel processing.

I suggest you to use WCF. WCF has a request/reply message pattern, where one endpoint requests data from a second endpoint. The second endpoint replies. WCF is such a big topic and I am sorry that I can't dive into the detail here. But you could easily start with this video. And here are more videos for you.

==================== below is the old answer ===================

You could start a new thread for each event:

void processEvent(string xml, int …, out string resultXML, out string description)
{
   new Thread(Handler).Start(xml);
}

void Handler(object xml)
{
    //do the actual work here
}

Each caller request will get responded by a thread immediately, so the caller will not be blocked. And each thread will quit automatically after finishing processing the request, so there will not be too many threads in your system.

This is just a simple solution. You might want to consider thread pooling in order to improve performance.

Peter Long
  • 3,964
  • 2
  • 22
  • 18
  • 1
    1 because this will kill the machine if a lot of event comes. – Felice Pollano Jun 23 '11 at 12:36
  • @Felice Pollano I said it was just a simple solution. If you want performance you'd have to use thread pooling(and take other necessary actions) – Peter Long Jun 23 '11 at 12:48
  • Your solution cannot work, the method processEvent must populate the output parameters before leaving, and it must be the actual result of the computation – Kill KRT Jun 23 '11 at 13:28
  • Actually I don't think the queue solution could solve your problem. You could follow the simple solution above and you could get the result, please refer to http://stackoverflow.com/questions/5233195/thread-with-return-type – Peter Long Jun 23 '11 at 14:37