Когда вы делаете _queueNotifier.Set()
событие становится сигнальным. Когда событие сигнализируется и _queueNotifier.WaitOne()
вызывается из другого потока, две вещи происходят одновременно (т.е. в режиме ядра):
- Событие становится неподписанным (так как оно автоматически сбрасывается)
- Поток, вызывающий
WaitOne
, разблокирован
Так что вам не нужно явно устанавливать статус события самостоятельно.
Однако, как говорит Джон, если единственное, что вы делаете с вашими общими переменными, - это выталкивание и извлечение элементов из очереди, просто использование BlockingCollection
более удобно.
Если вы обращаетесь к нескольким общим переменным, возможно, имеет смысл использовать механизм синхронизации одного потока (ваш собственный).
Кроме того, мне кажется, что если вы собираетесь использовать свой собственный код, было бы лучше сделать что-то вроде этого:
public void MoreData(Data example)
{
var queueWasEmpty = _queue.IsEmpty;
_queue.Enqueue(example);
if (queueWasEmpty) {
_queueNotifier.Set();
}
}
private void _SimpleThreadWorker()
{
while (_socket.Connected)
{
_queueNotifier.WaitOne();
Data data;
while(!queue.IsEmpty) {
if (_queue.TryDequeue(out data))
{
//handle the data
}
}
}
}
Таким образом, вам не нужно переходить в режим ядра (для установки события) всякий раз, когда элементы добавляются в очередь, пока функция потребителя занята. Вы также избегаете заходить в режим ядра на каждой итерации функции потребителя.
Это правда, что в отношении последнего избегание переключения контекста происходит за счет добавления теста _queue.IsEmpty
(где плохая реализация в любом случае может сделать переключение контекста); тем не менее, этот, вероятно, реализован как операция обмена с блокировкой сравнения, которая не требует перехода в режим ядра.
Отказ от ответственности: Я не проверял исходный код или IL для проверки вышеуказанной информации.