-
Есть поток, который занимается постоянным чтением из сокета через RecvFrom. В любой момент может быть приказ о завершении работы (приложение завершается).
Сигналом к тому, что пора завершаться является выставление у потока (в виде класса от TThread) свойства Terminated в true и дерганье определенного эвента, допустим WorkEvent;
Не могу понять, как элегантно отслеживать данные ситуации.
- если впрямую использовать RecvFrom, то при отсутствии данных поток зависнет в блокировке. Соответственно, так и будет висеть и никакими сигналами его не разбудить. Плохо.
- есть такая функция select, ее можно использовать, но это только частично решает проблему. То есть, можно делать select на определенный TimeOut. После отвисания проверять свойство Terminated и опять select.
Но тут проблема в том, чтобы выбрать оптимальный TimeOut. Чем он меньше - тем больше загрузка процессора на перепроверки, входы / выходы в синхронизацию и так далее. Чем больше TimeOut - тем медленнее средняя реакция потока на уведомления о завершении потока.
- в идеале я вижу это как вызов: WaitForMultipleObject от двух объектов. С одной стороны, WorkEvent который дернется если потоку нужно завершаться, с другой стороны некий объект синхронизации, говорящий о том, что в сокет поступили данные. Вот наверняка есть же такой объект, который можно впихнуть в WaitXXX функции. Но найти его не могу )))
Подскажите что делать, а скорее всего ответ просто в указании на соответствующий WinSock функции, которые позволяют создать такой объект.
-
> соответствующий WinSock функции, которые позволяют создать
> такой объект
Ты не поверишь - это хорошо известная и всенароднолюбимая ф-ция WinAPI CreateEvent()
И используется этот ивент в ф-ции WSAEventSelect
> в идеале я вижу это как вызов: WaitForMultipleObject от
> двух объектов
Далеко не единственное и не всегда идеальное решение.
Есть еще и MsgWaitForMultipleObjects. В комплексе с WSAEnumNetworkEvents позволяет преодолеть все мыслимые "неудобства".
> если впрямую использовать RecvFrom, то при отсутствии данных
> поток зависнет в блокировке
Ничто не мешает закрыть хэндл гнезда из другого потока - блокирующая ф-ция тут же "отвиснет" с соответствующим ожидаемым кодом отказа.
Это весьма распространенный и вполне коррекный способ прерывания блокирующей операции ввода-вывода.
-
Собссно говоря, ф-ция такая имеется - WSACreateEvent.
Но она не более чем раппер для CreateEvent.
-
> можно делать select на определенный TimeOut
В Indy именно так и реализовано. И никто не жалуется. А робкие жалобы перекрываются железным аргументом - кроссплатформенностью такого решения.
-
Закрыть сокет и Recvы отвалятся
It's not me (04.03.09 19:51)
Сигналом к тому, что пора завершаться является выставление у потока (в виде класса от TThread) свойства Terminated в true
и потом Socket.Close;
-
> Ничто не мешает закрыть хэндл гнезда из другого потока -
> блокирующая ф-ция тут же "отвиснет" с соответствующим ожидаемым
> кодом отказа.
>
> Это весьма распространенный и вполне коррекный способ прерывания
> блокирующей операции ввода-вывода
корректный?! То есть, это вполне документировано? Ну тогда так и сделаю, спасибо большое!
-
> It's not me (05.03.09 11:53) [5]
>
>
> так и сделаю
Тогда возникунут проблемы с совместимостью решения с другими платформами.
При неблок.режиме и select-мультиплексировании c таймаутом такавя проблема не возникнет.
-
> Тогда возникунут проблемы с совместимостью решения с другими
> платформами
с линуксом что ли? ))))
Я даже не планирую делать кроссплатформенную систему. Там несовместимостей будет как грязи )))
-
> даже не планирую делать кроссплатформенную систему
Тогда есть ненулевой резон задействовать возможности асинхронного режима, характерные именно для WSP - семейство WSAxxx-ф-ций, в частности WSA[Async/Event]Select, о которых ты заикнулся в самом начале.
-
А нафига? Так закрытие сокета из другого потока, когда первичный поток висит на RecvFrom нормально или все таки не очень нормально?
-
MS это не комментирует.
Но судя по фактической успешности такого решения для Winsock 2 (никакие проблемы при этом не наблюдаются) оно имеет право на жизнь.