Как асинхронно помещать в очередь (строку) сообщения из одного потока в другой в .NET 2.0 / 3.5? - PullRequest
2 голосов
/ 24 марта 2012

Я нашел статью о том, что я хочу реализовать в Реализация очереди в C # .Но статья основана на .Net 4.0.и сайт MSDN имеет только очень простой пример.поэтому решил опубликовать это здесь.

То есть я хотел бы реализовать, чтобы поток отображал строку асинхронно в окне приглашения DOS, беря строку из очереди.Другой поток может также добавить дополнительные строки в очередь строк асинхронно (максимальная запись строки равна 20, после заполнения максимальной записи больше нет добавления).И я хотел бы запустить это приложение, пока очередь не станет пустой на основе .Net 2.0 или 3.5. (VS2008)

Реализация очереди выглядит простой, потому что .Net предоставляет ее, но я не знаю, как реализоватьасинхронная часть с этой очередью.

Спасибо.

1 Ответ

5 голосов
/ 24 марта 2012

Итак, я понял, что вы хотите использовать по существу ConcurrentQueue, но вы застряли в .NET 3.5 и не можете его использовать (потому что он не существует).

Это восходит к простой операции блокировки. Вы не хотите, чтобы два потока обращались к одному и тому же объекту одновременно.

Перед началом работы : Читать Эта книга по C # Threading Джозефом Альбахари

Он распространяется на потоки .NET, и даже простое его сглаживание поможет вам избежать грубых ошибок потоков.

Есть две вещи, которые вам по сути нужно сделать, поэтому давайте разберемся с этим:

Безопасный доступ к очереди

Вы можете использовать Generic Queue<T> Class для реализации своей очереди сообщений, однако все операции, которые изменяют этот объект, должны безопасно обрабатываться.

Простейшей формой этого является использование оператора блокировки .

lock(myQueue)
{
   myQueue.Enqueue(message);
}

Вы должны заблокировать все операции, поэтому вам нужно указать три .Enqueue(...), .Dequeue() и .Count, поскольку все они имеют доступ к данным.

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

Ожидание сообщения

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

Самым простым является Thread.Sleep Петля

while(appIsRunning)
{
    Thread.Sleep(100);
    lock(myQueue)
    {
        while(myQueue.Count > 0)
        {
           Console.WriteLine(myQueue.Dequeue());
        }
    }
}

Примечание. Это не ЛУЧШИЙ способ сделать это, просто самый простой пример

То, что это делает, просто планирует этот поток для запуска снова, по крайней мере, через 100 мс. (Нет гарантии, что он будет работать через 100 мс, но не раньше того времени). Затем он блокирует очередь, поэтому запись в нее невозможна, он очищает очередь и записывает строки на экран, а затем снова зацикливается.

Если очередь пуста, она просто вернется в спящий режим.

Другое решение использует Pulse / Wait

Monitor.Pulse и Monitor.Wait - парадигма управления потоками в стиле пинг-понга.

Вы можете иметь свой цикл в главном потоке Monitor.Wait(), а когда вы добавляете сообщение в очередь, вы можете Monitor.Pulse() снять блокировку с ожидающего потока.

Это более семантически релевантно, но, вероятно, менее эффективно, потому что переключение контекста происходит по требованию для каждого сообщения.

Существует около 10 других способов сделать это, большинство из них описаны в этой книге, но это по сути дела.

См. Раздел сигнализации о событиях в книге Иосифа , где приведены примеры всех методов сигнализации.

...