The TryDequeue in ConcurrentQueue 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
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.
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;
}
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.
精彩评论