C # - Queue Management, что всегда запускается и Dequeing - PullRequest
2 голосов
/ 26 марта 2012

Мне нужно построить процесс, который прослушивает в WCF новые задачи.(Async) Каждое задание ставится в очередь (как-то).

Каков наилучший (логический и производительный) способ зацикливания очереди и ее удаления из очереди.

Я думал о:

while(true){
   queue.Dequeue();
}

Я предполагаю, что есть лучшие способысделать это.

Спасибо

Ответы [ 2 ]

7 голосов
/ 26 марта 2012

Взгляните на System.Collections.Concurrent Пространство имен - есть реализация потоковобезопасной очереди, а именно. ConcurrentQueue - хотя, я подозреваю, что ваши нужды будут лучше обслуживаться BlockingCollection .

Блокирующая коллекция - это, по сути, потокобезопасная коллекция, полезная для сценария производитель-потребитель. В вашем случае вызовы WCF будут выступать в качестве производителей, которые будут добавлять в коллекцию, в то время как рабочий поток будет выступать в роли потребителя, который, по сути, будет брать задачи из коллекции из очереди. Используя одного потребителя (и коллекции), вы можете обеспечить порядок выполнения. Если это не важно, то вы можете использовать несколько пользовательских потоков. (Существуют также AddAny и TakeAny статические перегрузки, которые позволят вам использовать несколько коллекций (несколько очередей), если это необходимо.)

Преимущество по сравнению с while(true) заключается в избежании замкнутого цикла, который будет просто потреблять циклы ЦП. Помимо обеспечения безопасности потока это также решило бы проблему синхронизации между очередями и потоками вывода из очереди.

EDIT

Blocking Collection действительно очень прост в использовании. Ниже приведен простой пример - добавление задачи будет вызвано, скажем, вашими методами WCF для постановки в очередь задач, в то время как StartConsumer будет вызываться во время запуска службы.

public class MyTask { ... }

private BlockingCollection<MyTask> _tasks = new BlockingCollection<MyTask>();

private void AddTask(MyTask task)
{
  _tasks.Add(task);
}

private void StartConsumer()
{
   // I have used a task API but you can very well launch a new thread instead of task
   Task.Factory.StartNew(() =>
     {
        while (!_tasks.IsCompleted)
        {
            var task = _tasks.Take();
            ProcessTask(task);
        }
     });
}

При остановке службы необходимо вызвать _tasks.CompleteAdding, чтобы потребительский поток прервался.

Найти больше примеров на MSDN:

http://msdn.microsoft.com/en-us/library/dd997306.aspx
http://msdn.microsoft.com/en-us/library/dd460690.aspx
http://msdn.microsoft.com/en-us/library/dd460684.aspx

0 голосов
/ 26 марта 2012

Вместо бесконечного цикла я бы использовал события для синхронизации очереди. Всякий раз, когда выполняется вызов WCF, добавьте элемент в очередь и отправьте «AnElementHasBeenAddedEvent».

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

Убедитесь, что только один поток выполняет эту работу!

Преимущества над концепцией while (true): у вас нет потока, который постоянно проходит по бесконечному циклу и, таким образом, потребляет ресурсы. Вы выполняете столько работы, сколько вам нужно.

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