Try Dequeue in ConcurrentQueue
Asked Answered
P

3

31

The TryDequeue in ConcurrentQueue<T> will return false if no items in queue.

If the queue is empty I need that my queue will wait until new item to be added in queue and it dequeue that new one, and the process will continues like that.

Should I use Monitor.Enter, Wait, Pulse or any better options in C# 4.0?

Previous answered 16/2, 2011 at 8:24 Comment(6)
hmmm - it surprises me that this isn't conveniently exposed - it seems like a common use-case...Brosy
I think with 4.0 a BCL class should expose this, but if nothing else appears, perhaps look at this answer, in which TryDequeue will block until either there is an item (returning true) or the queue is empty and explicitly shut down (returning false)Brosy
If the Queue is empty I need that my Thread will wait until new item to be added in queue and it dequeue that new one, and the process will continues like that.Previous
@Marc : I need to resume my thread to dequeue atonce the new item is added. How can i achieve this.Previous
the above does that, but it looks like "Damien_The_Unbeliever" has the answer hereBrosy
Old question, but people coming here may also want to check out this answer that suggests using a BufferBlock<T>, which allows async waiting.Syzran
G
55

Isn't this what BlockingCollection is designed for?

As I understand it, you can wrap your ConcurrentQueue with one of these, and then call Take.

Gigantean answered 16/2, 2011 at 8:45 Comment(0)
M
3

You can use BlockingCollection.

Do something like that:

private BlockingCollection<string> rowsQueue;
private void ProcessFiles() {
   this.rowsQueue = new BlockingCollection<string>(new ConcurrentBag<string>(), 1000);
   ReadFiles(new List<string>() { "file1.txt", "file2.txt" });


   while (!this.rowsQueue.IsCompleted || this.rowsQueue.Count > 0)
   {
       string line = this.rowsQueue.Take();

       // Do something
   }
}

private Task ReadFiles(List<string> fileNames)
{
    Task task = new Task(() =>
    {
        Parallel.ForEach(
        fileNames,
        new ParallelOptions
        {
            MaxDegreeOfParallelism = 10
        },
            (fileName) =>
            {
                using (StreamReader sr = File.OpenText(fileName))
                {
                    string line = String.Empty;
                    while ((line = sr.ReadLine()) != null)
                    {
                           this.rowsQueue.Add(line);
                    }
                }
            });

        this.rowsQueue.CompleteAdding();
    });

    task.Start();

    return task;
}
Moderate answered 14/8, 2018 at 22:51 Comment(0)
D
-2

You could periodically check the number of elements in the queue and when the number of elements is greater than zero, you give a signal using e.g. ManualResetEvent to the thread which dequeues the element(s) until the queue is empty.

Here is the pseudo code for this:

Check Thread:

while(true)
{
  int QueueLength = 0;
  lock(Queue)
  {
    queueLength = Queue.Length;
  }

  if (Queue.Length > 0)
  {
    manualResetEvent.Set();
  }
  else
  {
    Thread.Sleep(...);
  }       
}    

Dequeue Thread:

while(true)
{
  if(manualResetEvent.WaitOne(timeout))
  {
    DequeueUntilQueueEmpty();
  }
}

Consider using lock in the DequeueUntilQueueEmpty, too.

Dissimilitude answered 16/2, 2011 at 8:41 Comment(3)
Actually im using Monitor.enter,wait,pulseall to make the thread wait and signal. Is ManualResetEvent a better option?Previous
Actually im using Monitor.enter,wait,pulseall to make the thread wait and signal. Is ManualResetEvent a better option?Previous
ManualResetEvent is lightweight option, Monitor is a heavy one.Dissimilitude

© 2022 - 2024 — McMap. All rights reserved.