Попробуйте Dequeue в ConcurrentQueue - PullRequest
       21

Попробуйте Dequeue в ConcurrentQueue

22 голосов
/ 16 февраля 2011

TryDequeue в ConcurrentQueue вернет false, если в очереди нет элементов.

Если очередь пуста, мне нужно, чтобы моя очередь ожидала добавления нового элемента в очередь и удаляла этот новый, ипроцесс будет продолжаться следующим образом.

Должен ли я использовать monitor.enter, wait, pulse или любые другие лучшие опции в C # 4.0

Ответы [ 3 ]

46 голосов
/ 16 февраля 2011

Разве это не то, для чего предназначена BlockingCollection ?

Насколько я понимаю, вы можете обернуть свой ConcurrentQueue одним из них, а затем вызвать Take .

0 голосов
/ 15 августа 2018

Вы можете использовать BlockingCollection .

Сделать что-то подобное:

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;
}
0 голосов
/ 16 февраля 2011

Вы можете периодически проверять количество элементов в очереди, а когда количество элементов больше нуля, вы подаете сигнал, например, с помощью. ManualResetEvent для потока, который удаляет элементы из очереди до тех пор, пока очередь не станет пустой.

Вот псевдокод для этого:

Проверка темы:

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

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

Тема очереди:

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

Также рассмотрите возможность использования блокировки в DequeueUntilQueueEmpty.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...