Queue read by multiple threads

H

Hollywood

I have a system in which I have a single thread that places data on a Queue.
Then I have one worker thread that waits until data is put on the thread and
dequeues the Queue and processes that information. Works just fine.

However, I possibly need 1..m worker threads that can act on the same piece
of data, i.e. when a dequeue happens on the Queue it can't be removed from
the Queue until all threads have used it. I've tried to come up with good
ways of doing this but haven't found anything I liked or has worked. I
think I'd really like to just get rid of the Queue and send the packet of
data when I trigger the waiting threads, i.e. an expanded ManualResetEvent.
That way each thread can get the same piece of data and process it
independently. However, ARE and MRE are sealed and I've not seen any good
information on replicating them to be able to extend them to send a packet
along with the set trigger.

Thoughts or comments?
 
J

J.Marsch

Just thinking off the top of my head, one way to do it would be to use a 2
stage queue: You would have one "main" queue, and multiple "secondary" or
work queues (one for each thread). When you need to post (enqueue) data,
you would always enqueue to the main queue. A single dispatcher thread
would dequeue items from the main queue and enqueue the data onto each work
queue:

work queue 1 -->
worker thread
--> main queue --> dispatch thread <
work queue2 -->
worker thread

There are some issues that could come up. If the data item in the queue is
a reference type, you might have to synchronize access to it (or deep-copy
it). If the data item is a value type, like a struct, you will end up with
copies of it.

I'm sure that there are probably more optimized patterns for handling this,
but off the top, I think that this would work.

If you want to extend the Manual Reset Event, you might have to write your
own implementation. I'm pretty sure that the MRE and ARE are just thin
wrappers over O/S level synchronization events. See CreateEvent() in the
Platform SDK (DLLs, Processes, and Threads)
 
J

Jon Skeet [C# MVP]

Hollywood said:
I have a system in which I have a single thread that places data on a Queue.
Then I have one worker thread that waits until data is put on the thread and
dequeues the Queue and processes that information. Works just fine.

However, I possibly need 1..m worker threads that can act on the same piece
of data, i.e. when a dequeue happens on the Queue it can't be removed from
the Queue until all threads have used it. I've tried to come up with good
ways of doing this but haven't found anything I liked or has worked. I
think I'd really like to just get rid of the Queue and send the packet of
data when I trigger the waiting threads, i.e. an expanded ManualResetEvent.
That way each thread can get the same piece of data and process it
independently. However, ARE and MRE are sealed and I've not seen any good
information on replicating them to be able to extend them to send a packet
along with the set trigger.

Thoughts or comments?

I suggest you have as many queues as you have threads, and put the same
work items on all of them. Any other way is going to make it a lot
harder to find out which is the next job, etc.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top