ManualResetEvent(EventWaitHandle) Set тратит больше ресурсов процессора, чем WaitOne(timeout)

При реализации ManualResetEvent меня что-то удивило,

Насколько я понимаю mre.Set() подает команду и позволяет другим процессам выполняться.

mre.WaitOne(); Держится на текущей линии и ждет сигнала. Кроме того, если мы используем его с тайм-аутом mre.WaitOne(100ms);

НО! Предположим, что StartCommunicate — это задание потока.

Если я использую waitHandle.Set();, мой процесс использует ~%25 или для другого проекта ~%1 ресурс ЦП.

Но если я использую waitHandle.WaitOne(100); (значение тайм-аута символическое. Он (попытка) ждет сигнала в течение 100 мс).

Процесс начинает использовать ~%0 ресурсов ЦП с waitone(timeout) Что это значит? ThereIsAJobToExecute — это Socket.HasData для меня. Значит ли это, что частое нажатие на SerialPort.BytesToRead или Socket.Available повышает загрузку ЦП?

Есть ли какой-либо побочный эффект для меня, удерживая поток в течение 100 мс для каждого попадания? Предположим, что программа сокетов или скорость передачи данных соединения rs232 очень низкая по сравнению с ПК нового поколения.

Поэтому использование mre.WaitOne(1); кажется мне более предпочтительным. Что вы думаете об этом ? Я провожу некоторые эксперименты с некоторыми профилировщиками памяти и производительности, но я не уверен, делаю ли я оптимальное решение для различных клиентских машин или нет...

Жду ваших комментариев.

Заранее спасибо!

    ManualResetEvent waitHandle = new ManualResetEvent(false);
    public void StartCommunicate()
    {
        while (true)
        {
            if (ThereIsAJobToExecute)
            {
                Execute the job here!
            }
            else {
                //waitHandle.Set();
                waitHandle.WaitOne(1);
            }                              
        }

    }

EDIT: Для программирования Socket доступна работа ASYN, поэтому мы можем легко сделать это с помощью приведенного ниже кода, и нам не нужен опрос.

Но программирование COMM-порта RS232 мне нужно. Или не ?

 do
 {
      socket.BeginReceiveASYN(....ReceiveCallBack,...,socket)
      mre.WaitOne();
      mre.Reset();
 }while(true)

     void ReceiveCallBack(IResult rst)
     {
     //get the socket and do my job here!
      mre.Set();
     }

person Davut Gürbüz    schedule 19.03.2014    source источник
comment
Set() и WaitOne редко взаимозаменяемы. Мне непонятно, почему вы думаете, что они в этом случае.   -  person Damien_The_Unbeliever    schedule 19.03.2014
comment
Обычно все, что генерирует «JobToExecute», выполняет сигнализацию. Это один из основных моментов связи между потоками - не требуется опрос для работы.   -  person Martin James    schedule 19.03.2014
comment
@MartinJames Я собираюсь отредактировать свой вопрос, чтобы сделать его более понятным.   -  person Davut Gürbüz    schedule 19.03.2014
comment
@Damien_The_Unbeliever, вы правы, на данный момент их работа отличается. Я только что заметил, что с помощью WaitOne я могу облегчить бремя потока, чтобы более эффективно использовать ЦП. Я предположил, что для опроса COM-порта не требуется слишком много процессорного времени. Я пытаюсь нарисовать диаграмму в реальном времени, получая 1000 байтов из com-порта, обрабатывая последовательные байты... Это настоящая работа. Я согласен, это звучит странно, но я стараюсь всеми способами добиться этого.   -  person Davut Gürbüz    schedule 19.03.2014
comment
Несправедливо сравнивать яблоки и апельсины. Set и WaitOne ортогональны. и .. кстати, ваш код асинхронного сокета тратит поток на ожидание, вы не получаете никакой масштабируемости от асинхронного, таким образом, лучше использовать синхронные сокеты, чем создавать поток для ожидания, пока вы не получите данные.   -  person Sriram Sakthivel    schedule 19.03.2014
comment
Но для синхронного я должен ждать if (SerialPort.BytesToRead>0) в бесконечном цикле. Это проблема. Я ошибся ? Есть ли способ уведомления о новых доступных данных на последовательном порту? Если это так, то все в порядке.   -  person Davut Gürbüz    schedule 19.03.2014
comment
Почему вы используете ввод-вывод на основе обратного вызова и ждете завершения обратного вызова? Просто используйте синхронную версию. С последовательными портами просто прочитайте, какие из них будут заблокированы, пока не поступят данные.   -  person usr    schedule 19.03.2014
comment
ХОРОШО! Спасибо вам всем. Я думаю, что понял. В SerialPort есть событие DataReceived, я его использую. Тогда не нужно голосование для этого.   -  person Davut Gürbüz    schedule 19.03.2014
comment
@usr Последовательный порт уже не поддерживает асинхронный. Я просто написал, как это нормально! для программы Socket. Спасибо.   -  person Davut Gürbüz    schedule 19.03.2014


Ответы (2)


WaitOne переводит поток в состояние приостановки, что не требует ресурсов ЦП. Сигнал от ManualResetEvent позже пробуждает поток.

person Haney    schedule 19.03.2014

Мне не совсем понятно, для чего вы используете ManualResetEvent. Однако...

Делать что-то вроде waitHandle.WaitOne(1) в значительной степени бессмысленно, так как вы спите в течение такого небольшого промежутка времени, что вы фактически заняты ожиданием этого потока и потребляете ресурсы ЦП, которые ничего не делают.

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

while(true)
{
  waitHandle.Wait();
  waitHandle.Reset();

  while(ThereIsAJobToExecute)
  {
    // Process the jobs
  }
}

Это усыпит ваш поток, когда нечего делать, и не будет тратить ресурсы. Теперь вы можете подать сигнал с помощью waitHandle.Set(), когда есть работа.

person Sean    schedule 19.03.2014
comment
Я думаю, что ваш код не будет работать, если состояние waitHandle ложно (если вы имели в виду waitone под ожиданием). Я предположил, что, ожидая периода, я просто выполнил работу сна таймера. Я сделал это, чтобы избежать чрезмерного использования ЦП при опросе, и я сделал это только тогда, когда нет работы. Если есть задание SYNC, оно завершает задание и снова опрашивает. Но работы нет, давайте немного подождем и спросим еще раз. Это что-то вроде того, чтобы не задавать мне один и тот же вопрос слишком часто. Это занимает больше времени, чем NOP. Вы читали комментарии, прежде чем отвечать? - person Davut Gürbüz; 19.03.2014
comment
Если событие не сигнализируется, то поток будет спать, пока не станет сигнализированным. Если у него нет задачи для выполнения, что бы вы хотели, чтобы он делал вместо сна? Ваш вопрос не очень ясен о том, что вы пытаетесь сделать, поэтому я сделал наилучшее предположение. - person Sean; 19.03.2014
comment
Предположим, что есть задание опроса. У вас нет уведомления об изменении. Затем вы задаете его в непрерывном цикле. Но определение того, есть ли работа или нет [это становится другой работой], требует времени, и нет необходимости очень часто просить об этой смене. Кстати, вы спрашиваете, редко ли вы освобождаете некоторые ресурсы ЦП ради -нет выполнения IsThereAJobMethod-. Я задал вопрос, чтобы понять, что происходит на самом деле. Я думаю, что Дэвид Хейни прав. - person Davut Gürbüz; 19.03.2014
comment
Я просто не знал, что событие SerialPort DataReceived можно использовать в качестве уведомления. Теперь мой вопрос недействителен для программирования сокетов или программирования последовательного порта. Я думал, что единственный способ опросил его, но нет. Простите за недопонимание. - person Davut Gürbüz; 19.03.2014