Как отправить рабочие элементы в один поток - PullRequest
3 голосов
/ 23 февраля 2010

Извините, этот вопрос не очень понятен, если я знаю правильные слова для описания проблемы, Google, скорее всего, найдет ответ.

Я ищу класс очереди, который:

  • Позволяет любому количеству потоков поместить элемент в очередь.
  • Элементы обрабатываются в порядке их добавления в очередь
  • Я не против, какой поток обрабатывает элемент
  • Одновременно обрабатывается только один элемент.
  • Скорее всего, у меня нет заблокированного потока, ожидающего добавления элемента в очередь, если в очереди нет элементов.
  • Нормальный случай - пустая очередь большую часть времени.

например, точно так же, как то, что происходит с BeginInvoke в окнах WinForms ... (или PostMessage, если вы все сделали сырое программирование на win32) Мы используем .net 3.5

Я ищу что-то готовое в .net framework или проект с открытым исходным кодом, который имеет хорошие модульные тесты, так как я не хочу писать все модульные тесты для решения домашнего изготовления.


Для справки см. Почему мое сообщение обрабатывается не по порядку по одному TCP-каналу WCF (с ConcurrencyMode.Reentrant)? с помощью этого депатчера я смог перейти на использование ConcurrencyMode.Single и все еще избегайте тупиков.

Ответы [ 3 ]

4 голосов
/ 23 февраля 2010

Вот эскиз класса, который может это сделать:

public class WorkerQueue<T> {
    private Queue<T> workerQueue   = new Queue<T>();
    private object   padlock       = new object();
    private bool     isProcessing  = false;
    private Thread   workerThread;

    public void QueueWorkItem(T item) {
        lock(padlock) {
            workerQueue.Enqueue(item);
            if (!isProcessing) {
                isProcessing = true;
                workerThread = new Thread(() => { this.ProcessWork });
                workerThread.Start();

            }
        }
    }

    private void ProcessWork() {
        // 1) Thread-safe dequeue operation
        // 2) Keep processing while work is on the queue. External callers can
        //    add items to the queue while this is ongoing.
        // 3) When the queue is empty, set isProcessing to false (thread-safely)
    }

}

Приложения будут использовать это так:

public class Application {
    private WorkerQueue<object> workerQueue = new WorkerQueue<object>();

    // This can run on multiple threads if need be
    public void SomeMethodThatCreatesWork() {
        object workItem = ExternalCall();
        this.workerQueue.QueueWorkItem(workItem);
    }
}

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

1 голос
/ 23 февраля 2010

Используйте CCR , который предоставляет примитивы порта, которые являются эффективными очередями FIFO, и примитивы Dispatcher, DispatcherQueues и Arbiter, которые позволяют контролировать планирование задач.

0 голосов
/ 23 февраля 2010

Используйте ThreadPool, но используйте SetMaxThreads, чтобы ограничить количество запущенных потоков одним. Используйте QueueUserWorkItem, чтобы добавить больше задач в очередь. http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx

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