![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Зависание над чтением сокета
It's not me © (2009-03-04 19:51:00)Есть поток, который занимается постоянным чтением из сокета через RecvFrom. В любой момент может быть приказ о завершении работы (приложение завершается).
Сигналом к тому, что пора завершаться является выставление у потока (в виде класса от TThread) свойства Terminated в true и дерганье определенного эвента, допустим WorkEvent;
Не могу понять, как элегантно отслеживать данные ситуации.
- если впрямую использовать RecvFrom, то при отсутствии данных поток зависнет в блокировке. Соответственно, так и будет висеть и никакими сигналами его не разбудить. Плохо.
- есть такая функция select, ее можно использовать, но это только частично решает проблему. То есть, можно делать select на определенный TimeOut. После отвисания проверять свойство Terminated и опять select.
Но тут проблема в том, чтобы выбрать оптимальный TimeOut. Чем он меньше - тем больше загрузка процессора на перепроверки, входы / выходы в синхронизацию и так далее. Чем больше TimeOut - тем медленнее средняя реакция потока на уведомления о завершении потока.
- в идеале я вижу это как вызов: WaitForMultipleObject от двух объектов. С одной стороны, WorkEvent который дернется если потоку нужно завершаться, с другой стороны некий объект синхронизации, говорящий о том, что в сокет поступили данные. Вот наверняка есть же такой объект, который можно впихнуть в WaitXXX функции. Но найти его не могу )))
Подскажите что делать, а скорее всего ответ просто в указании на соответствующий WinSock функции, которые позволяют создать такой объект.
Сергей М. (2009-03-05 14:24:00) [1]MS это не комментирует.
Но судя по фактической успешности такого решения для Winsock 2(никакие проблемы при этом не наблюдаются) оно имеет право на жизнь.
It's not me (2009-03-05 13:56:00) [2]А нафига? Так закрытие сокета из другого потока, когда первичный поток висит на RecvFrom нормально или все таки не очень нормально?
Сергей М. (2009-03-05 13:28:00) [3]
> даже не планирую делать кроссплатформенную систему
Тогда есть ненулевой резон задействовать возможности асинхронного режима, характерные именно для WSP - семейство WSAxxx-ф-ций, в частности WSA[Async/Event]Select, о которых ты заикнулся в самом начале.
It's not me (2009-03-05 13:23:00) [4]
> Тогда возникунут проблемы с совместимостью решения с другими
> платформами
с линуксом что ли? ))))
Я даже не планирую делать кроссплатформенную систему. Там несовместимостей будет как грязи )))
Сергей М. (2009-03-05 12:45:00) [5]
> It's not me (05.03.09 11:53) [5]
>
>
> так и сделаю
Тогда возникунут проблемы с совместимостью решения с другими платформами.
При неблок.режиме и select-мультиплексировании c таймаутом такавя проблема не возникнет.
It's not me (2009-03-05 11:53:00) [6]
> Ничто не мешает закрыть хэндл гнезда из другого потока -
> блокирующая ф-ция тут же "отвиснет" с соответствующим ожидаемым
> кодом отказа.
>
> Это весьма распространенный и вполне коррекный способ прерывания
> блокирующей операции ввода-вывода
корректный?! То есть, это вполне документировано? Ну тогда так и сделаю, спасибо большое!
Slym (2009-03-05 04:46:00) [7]Закрыть сокет и Recvы отвалятся
It's not me (04.03.09 19:51)
Сигналом к тому, что пора завершаться является выставление у потока (в виде класса от TThread) свойства Terminated в true
и потом Socket.Close;
Сергей М. (2009-03-04 20:16:00) [8]
> можно делать select на определенный TimeOut
В Indy именно так и реализовано. И никто не жалуется. А робкие жалобы перекрываются железным аргументом - кроссплатформенностью такого решения.
Сергей М. (2009-03-04 20:09:00) [9]Собссно говоря, ф-ция такая имеется - WSACreateEvent.
Но она не более чем раппер для CreateEvent.
Сергей М. (2009-03-04 20:04:00) [10]
> соответствующий WinSock функции, которые позволяют создать
> такой объект
Ты не поверишь - это хорошо известная и всенароднолюбимая ф-ция WinAPI CreateEvent()
И используется этот ивент в ф-ции WSAEventSelect
> в идеале я вижу это как вызов: WaitForMultipleObject от
> двух объектов
Далеко не единственное и не всегда идеальное решение.
Есть еще и MsgWaitForMultipleObjects. В комплексе с WSAEnumNetworkEvents позволяет преодолеть все мыслимые "неудобства".
> если впрямую использовать RecvFrom, то при отсутствии данных
> поток зависнет в блокировке
Ничто не мешает закрыть хэндл гнезда из другого потока - блокирующая ф-ция тут же "отвиснет" с соответствующим ожидаемым кодом отказа.
Это весьма распространенный и вполне коррекный способ прерывания блокирующей операции ввода-вывода.