views:

75

answers:

4
public void EnqueueTask(int[] task)
{
    lock (_locker)
    {
        _taskQ.Enqueue(task);
        Monitor.PulseAll(_locker);
    }
}

So, here I'm adding elements to my queue and than threads do some work with them.How can I add items to my queue asynchronously?

A: 

Maybe something like this could work:

void AddToQueue(Queue queue, string mess) {
    var t = new Thread(() => Queue.Synchronized(queue).Enqueue(mess));
    t.Start();
}

The new thread ensures that your current thread does not block.

Queue.Syncronized handles all locking of the queue. It could be replaced with your locker code, might be better performance.

David Mårtensson
+1  A: 

If you using .net V4 have a look at the new thread safe collections, they are mostly none blocking so will properly avoid the need for an async add.

Ian Ringrose
ConcurrentQueue<T>
taras.roshko
BTW,thanks :). I had bookmarks with the new thread-safe collections from .NET 4 and you helped me to remember about them)
taras.roshko
A: 

Since your using Queue<T> (recommended), Queue.Synchronized can't be used.

But besides that I would use the thread pool. But your EnqueueTask method kind of implies that the threading logic is handled outside of your "TaskQueue" class (your method implies that it is a Queue of tasks).

Your implementation also implies that it is not "Here" we wan't to add logic but rather in another place, the code you have there isn't really blocking for long so I would turn things upside down.

It also implies that the thing taking things off the queue is already on another thread since you use "PulseAll" to weak that thread up.

E.g.

public void StartQueueHandler()
{ 
  new Thread(()=>StartWorker).Start();
}

private int[] Dequeue()
{
  lock(_locker)
  {
    while(_taskQ.Count == 0) Monitor.Wait(_locker);
    return _taskQ.Dequeue();
  }
}

private void StartWorker(object obj)
{
  while(_keepProcessing)
  { 
    //Handle thread abort or have another "shot down" mechanism.
    int[] work = Dequeue();

    //If work should be done in parallel without results.
    ThreadPool.QueueUserWorkItem(obj => DoWork(work));

    //If work should be done sequential according to the queue.
    DoWork(work);
  }
}
Jens
You're right, I'm processing tasks from queue in many threads and want to add capability to add elements asynchronously.Thank's for your reply, but I decided to use "ConcurrentQueue<T>", IMHO, I'ts esiest way :)
taras.roshko
The question is why do you wan't to add that capability? What will happen is that you start a thread to add an element and the thread dies within a very few milliseconds again since "Adding" an element (if done right) won't block you. Having to start up a new thread and start it may take longer than just doing it synchronously. Obviously somewhere outside you have one or more "Threads" that will in turn add something, e.g. by the user clicking an button or data incoming on a port etc. But you would most likely handle that there. Extending your "Enqueue" method to be Async won't benefit you.
Jens
It's not my decision, the task is about that)
taras.roshko
I'm using async delegates to add items to queue asynchronously,than special adding manager takes care about loading every core on PC
taras.roshko
A: 

The code from your question seems to indicate that you are attempting to implement a blocking queue. I make that obseration from the call to Monitor.PulseAll after the Queue<T>.Enqueue. This is the normal pattern for signalling the dequeuing thread. So if that is the case then the best option is to use the BlockingCollection class which is available in .NET 4.0.

Brian Gideon