2015-12-17 19 views
0

В этой статье Embarcadero описывается использование блокирующего сокета внутри потока. Если я создал свой сокет ctNonBlocking и я только писать простые сообщения в сокет я должен использовать TClientWinSocket.SendText:Используйте неблокирующий TClientSocket внутри потока

// Inside TThread::Execute: Option 1 
strMessage := 'Hello!'; 
mySocket.Socket.SendText(strMessage); 

или я должен создать TWinSocketStream и используя Write:

// Inside TThread::Execute: Option 2 
strMessage := 'Hello!'; 
stream := TWinSocketStream.Create(mySocket.Socket, 1000); 
stream.Write(strMessage[1], Length(strMessage)); 

Что Я нахожу, что мое приложение выдает исключение при выходе (после Application.Run() в DPR-файле и невозможно отладить), которое исчезает, если я прокомментирую весь код TClientSocket.

+0

Почему вы делаете эту странную вещь? Если вы собираетесь поднимать поток, почему не блокируете? Где вызов вашего конструктора для экземпляра TClientSocket? Пожалуйста, не говорите, что вы сбросили его на форму: (( –

+0

Сокет создается в функции инициализации потока сразу после создания потока, как в 'mySocket: = TClientSocket.Create (nil);', а затем 'mySocket. ClientType: = ctNonBlocking; '. Я установил сокет как неблокирующий, потому что мне показалось проще, но я здесь, чтобы узнать. Если это странно, то я посмотрю на блокирующий вариант ... – AlainD

+0

См. Комментарий к принятому решению. В основном я следовал примеру кода в статье Embarcadero, упомянутой в вопросе (преобразование TClientSocket из режима неблокирования в блокирующий). Это оказалось относительно простым. Конечно, способ, которым я пользовался раньше, был «странным «... использование его в режиме блокировки внутри потока отлично работает! – AlainD

ответ

1

Вы не можете использовать TWinSocketStream, если разъем находится в неблокирующем режиме. TWinSocketStream создаст исключение, если сокет не находится в режиме блокировки. Об этом говорится в documentation:

Используйте TWinSocketStream для чтения или записи информации поверх блокирующего соединения гнезда ...

...

Примечание: TWinSocketStream не работает с , не -блока розетки.

TClientSocket в режиме неблокирования работает нормально в рабочем потоке (хотя предпочтительным является режим блокировки) при условии, что поток имеет контур сообщения. Причина в том, что в неблокирующем режиме TClientSocket создает внутреннее окно и связывает его с сокетом. Это окно получает сообщения от WinSock для запуска событий TClientSocket. Таким образом, TClientSocket в неблокирующем режиме необходимо создавать, использовать и уничтожать в рамках одного и того же контекста потока. Не обращайтесь к ним через границы потоков.

TClientSocket в режиме блокировки не имеет этого ограничения.

+3

Я бы избегал TClientSocket в неблокирующем режиме в потоках. Он использует AllocateHWnd для создания своего окна, и эта функция не является потокобезопасной. работа mos т времени, но потом провалится здесь и там. –

+0

Доступ к TClientSocket осуществляется только из одного потока. Единственный способ, которым «внешний мир» взаимодействует с потоком, - это добавлять сообщения в TStringList (завернутый критической секцией для синхронизации) или получать статистику из потока, например, сколько сообщений было отправлено. Поток проверяет наличие новых сообщений в TThread :: Execute. Спасибо за комментарии Remy, посмотрим на переключение на блокирующие вызовы сокетов. – AlainD

+0

@Remy: Быстрый вопрос, связанный с 'TWinSocketStream'.Документация (и образец Embarcadero) показывает, что «TWinSocketStream» создается, используется и затем освобождается каждый раз. Есть ли проблема с созданием «TWinSocketStream» один раз и повторное использование его снова и снова? В исходном вопросе, если сокет был изменен на блокировку, '' TWinSocketStream' предпочитает 'Socket.SendText (...);'? – AlainD

Смежные вопросы