Какой самый эффективный способ «тратить время» в потоке? - PullRequest
11 голосов
/ 01 ноября 2011

У меня есть несколько потоков (100), каждый из которых выполняется по несколько секунд за раз.Когда они выполняются, они тратят значительное количество этого времени на ожидание ответа от другой системы (последовательного устройства).Я помнил, что одновременное выполнение 100 потоков может привести к потере ресурсов, поэтому я ограничиваю количество потоков, которые могут запускаться одновременно.

Мне кажется, что должны быть хорошие и плохие способы.ожидания внешнего события внутри потока.Является ли этот подход ресурсоемким?:

send command ;
repeat
until response arrived ;
process response ;    

и делает ли этот подход его более эффективным?:

send command ;
repeat
    Sleep (20) ;
until response arrived ;
process response ;  

* ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ *

Среда x86 для Windows XP.Код потока представляет собой длинную и сложную серию взаимодействий с последовательным устройством, но в целом он состоит из записи символов в COM-порт (с использованием последовательной библиотеки AsyncFree) и ожидания возврата символов путем размещения в буфере входящих символов иобрабатывая их, когда они прибывают.Я представляю, что последовательная библиотека выполняет чтение и запись устройства.Время в потоке может составлять минуту или пару секунд, но большая часть этого времени тратится на ожидание символов, покидающих порт, или на ожидание символов ответа (скорость передачи данных низкая),отсюда мой вопрос о том, как лучше вести поток, пока он ждет.В настоящее время я вызываю Sleep в цикле, ожидая, пока CharactersInBuffer станет ненулевым, обрабатывая каждый символ, когда он прибывает, и покидая поток, когда у меня есть полный ответ.Таким образом, код выглядит примерно так (без учета обработки тайм-аутов и т. Д.):

send command ;
Packet = '' ;
repeat

    repeat
        Sleep (20) ;
    until response character arrived ;
    build Packet

until complete packet arrived
process response ;  

Ответы [ 3 ]

7 голосов
/ 01 ноября 2011

Если поток действительно ожидает с чем-то вроде WaitForSingleObject, который не использует процессорное время, то время ожидания истекло, поэтому нет никакой причины помещать задержку в поток со сном.

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

Как отметил Дэвид Хеффернан в своем комментарии, если сейчас он не использует 100% вашего процессора, то проблем нет.

Вы могли бы использовать sleep (), если вы были однопоточными, и вам приходилось время от времени отвечать пользователю в промежутке между ожиданием ответа от последовательного порта.

Кроме того, спящий поток не сделает его более эффективным. Это просто дало бы циклы процессора другим потокам.

Взгляните на sleep(0) как эффективный для ЦП способ «тратить время» в потоке.

2 голосов
/ 02 ноября 2011

Я не могу говорить о возможностях AsyncFree, но в целом программирование COM-порта в Windows поддерживает перекрывающийся ввод-вывод, поэтому вы можете эффективно ожидать уведомления при получении данных с помощью функции WaitCommEvent() с одним из семейств WaitFor...() функций, таких как WaitForSingleObject(). Поток может быть переведен в состояние сна до тех пор, пока не возникнет проблема с уведомлением, когда он «просыпается» для чтения из порта, пока больше нечего читать, затем он может вернуться в спящий режим до следующего уведомления.

2 голосов
/ 01 ноября 2011

Самый эффективный способ предотвратить использование процессорного времени потоком - перевести его в «режим ожидания».

Я вообще не использую delphi, но, похоже, основные принципы для этоготам.См. «Глава 11. Синхронизаторы и события» и более конкретно «Моделирование событий с использованием семафоров» .

Если вы хотите ждать без использования ЦП, используйте WaitForEvent:

Состояние сигнала события проверяется.Если это указывает, что событие сигнализировано, то внутренний семафор сигнализируется, и число потоков, заблокированных на семафоре, уменьшается.Затем число заблокированных потоков увеличивается, и на внутреннем семафоре выполняется ожидание.

Если это связано с вводом / выводом, то все работает немного иначе.Если это сокет, то он, возможно, уже блокируется, если это асинхронный ввод-вывод, тогда вы можете использовать семафор и WaitForEvent и т. Д.

В .NET есть Monitor.Wait, Monitor.Signal, ManualResetEvent, CountDownLatch и т. Д., Но я не знаю, что эквивалентно в Delphi.

...