Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

TClientSocket в TThread не работает... [D6, Win95/98]


Страницы:   1 2 3

Donal_Graeme ©   (2002-04-10 18:09:00) 

ничего не понимаю...
в главной форме работает, внутри метода потока Execute - не работает. один и тот же код :

FTCP.Host := Host;
FTCP.Port := StrToInt (Port);
FTCP.ClientType := ctNonBlocking;
FTCP.Open;

если в потоке, то работает так:
если Host задать неправильно, то он вываливается с ошибкой, т.е. работает, а если Host задан правильно, то коннекта не происходит и ошибок тоже не возникает.
хотя в основной программе коннектится и нормально работает.


Donal_Graeme   (2002-04-11 15:53:00) [21]

извиняюсь за сумбур :-))

в ctBlocking работает, в ctNonBlocking - не работает


Digitman   (2002-04-11 15:53:00) [22]

>Reindeer Moss Eater
>>"Надеюсь ты не станешь утверждать..."
Нет, не стану. Событие генерируется объектом VCL в ответ на получение Windows-сообщения CM_SOCKETMESSAGE от гнезда - объекта ОС.

>>"нитка, создавшая экземпляр TClientSocket "спит" и не обрабатывает сообщения ..."

А где ты видишь, что кто-то где-то шлет сообщения этой нитке ? Нет этого ни в коде автора ни в коде scktcomp.pas. Сообщения гнезда - объекта ОС посылаются в ОКНО, создаваемое объектом ClientWinSocket при активации ClientSocket, а Win32 автоматически вызывает оконную ф-ции этого окна.


Donal_Graeme   (2002-04-11 15:52:00) [23]

блин... и в nonBlocking тоже работает... ничего не менял...
может, более ранними тестами намусорил в памяти и поэтому не работало.


Donal_Graeme   (2002-04-11 15:50:00) [24]

интересно, поставил тип ctBlocking - работает. в смысле, коннектится.


Donal_Graeme   (2002-04-11 15:43:00) [25]

2 Digitman :

там тоже ставил. останов получил только в OnError на неправильный хост.

2 Reindeer Moss Eater :

но я же ловлю событие OnError, и выполняя там SetEvent нормально вываливаюсь из WaitForSingleObject


Reindeer Moss Eater   (2002-04-11 15:34:00) [26]

>Donal_Graeme
Попробуй сделать WaitForSingleObject в основном потоке и убедишься что событий никаких тоже не будет.


Digitman   (2002-04-11 15:30:00) [27]

>Donal_Graeme
Точку останова следовало ставить в теле OnConnect и OnError. Вот если и там не "ловится", тогда будем уточнять окружение всего того, от чего зависит поток


Reindeer Moss Eater   (2002-04-11 15:24:00) [28]

Надеюсь ты не станешь утверждать что СОБЫТИЕ в классе TClientSocket, в обработчике которого автор вопроса устанавливает Event для функции ожидания генерируется ОС.

Я утверждаю что событие не генерится из-за того, что нитка, создавшая экземпляр TClientSocket "спит" и не обрабатывает сообщения (waitforsingleobject)


Donal_Graeme   (2002-04-11 15:22:00) [29]

2 Digitman :

> Почему ты так уверен, что 5 секунд достаточно для работы
> запроса к DNS и установления соединения ?

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

насчёт того, действительно ли WaitForSingleObject ждёт заданное время - у меня там было и 50 секунд - висело ровно столько. Ещё я ставил точку останова на Wait и после - сразу вываливается только в случае неправильного хоста.

насчёт концептуальней правильно - это точно :-) переделаю.


Digitman   (2002-04-11 15:18:00) [30]

>Reindeer Moss Eater

ИМЕННО в данном случае класс TClientSocket инкапсулирует ф-ции управления ИМЕННО гнезда как объекта ОС. И ИМЕННО гнездо как объект ОС позволяет выбирать режим работы с ним как блокирующий (синхронный), так и неблокирующий (асинхронный). А вызывать ф-ции гнезда как объекта ОС можно в любом потоке, и никакой "синхронности" при этом не требуется.


Reindeer Moss Eater   (2002-04-11 14:56:00) [31]

Да мне безразлично Winsock API в этом конкретном случае.
Все что я говорил в этой ветке относится только к КЛАССАМ vcl и не более того.

Ты про асинхронный метод мне не ответил.


Digitman   (2002-04-11 14:51:00) [32]

А ты почитай дла начала описания WinsockAPI-ф-ций WSAAsyncSelect и WSAEventSelect ! Да посмотри, вызываются ли, как, в какой момент, в каких режимах и с какими параметрами хотя бы одна из этих ф-ций в реализации класса TClientSocket ! Тогда и поговорим)


Reindeer Moss Eater   (2002-04-11 14:48:00) [33]

> Donal_Graeme
если хочешь использовать сокет в потоке, то попробуй blocking режим и синхронные вызовы методов.


Reindeer Moss Eater   (2002-04-11 14:44:00) [34]

Все может быть.
Только объясни мне неверному такую вещь:
Если сокет использует nonblocking режим и вызов некого метода этого сокета асинхронный, то как реализовать этот метод внутри класса не используя потоки ?


Digitman   (2002-04-11 14:34:00) [35]

>Reindeer Moss Eater
Совершенно неверные у тебя представления о "потрохах" TClientSocket, работающем в режиме NonBlocking.
И "нитка внутри сокета" - выражение, лишенное смысла и логики.

Более того, ты "месишь в одну кучу" вещи совершенно разные, самостоятельные по сути и независящие друг от друга никак : "блокирующий режим работы" и "дополнительный кодовый поток"


Reindeer Moss Eater   (2002-04-11 14:17:00) [36]

>Digitman
Сокет у автора вопроса - nonblocking.
Значит где-то внутри класса создается поток.
Если в нем есть вызовы syncronize, то поток, создавший сам сокет должен продолжать обрабатывать очередь сообщений иначе нитка внутри сокета не будет выполнятся.


Digitman   (2002-04-11 14:02:00) [37]

>Reindeer Moss Eater
что это еще за "потоковый код сокета" ?
ты о событиях объекта TCustomWinSocket что ли ?


Reindeer Moss Eater   (2002-04-11 13:41:00) [38]

По моему нельзя морозить нить, создавшую сокет, если потоковый код сокета выполняется через syncronize.
Аналогичная ситуация у меня в ApdComPort из AsyncPro.


Digitman   (2002-04-11 13:28:00) [39]

1.
>>WaitForSingleObject (hEvent, 5000);// здесь ждёт сколько задано

Почему ты так уверен, что 5 секунд достаточно для работы запроса к DNS и установления соединения ?
Где анализ результата вызова WaitForSingleObject ? Он действительно "ждет" у тебя 5 сек ? Или возвращает управление сразу же после вызова ?

Концептуально правильней было бы реализовать участок ожидания сигнала события объекта hEvent в цикле, например, так :




MaxTimeOut: Dword; // поле, хранящее неизменяемый в процессе работы потока параметр макс.тайм-аута ожидания в цикле событий; параметр передается в конструкторе потока и может принимать значения либо INFINITE (ждать до бесконечности, пока либо соединение будет установлено, либо просигналит событие OnError()) либо заданное значение в м/сек, например, 60000

const
CyclicTimeOut = 1000; //тайм-аут для ф-ции ожидания

ActualTimeOut: DWord; //аккумулятор
...

ActualTimeOut := 0;
while not Terminated do
case WaitForSingleObject (hEvent, CyclicTimeOut) of// ждём недолго, чтобы оперативней реагировать на флаг Terminated
WAIT_OBJECT_0: break; // hEvent просигналил
WAIT_TIMEOUT:
begin
Inc(ActualTimeOut, CyclicTimeOut);//на всякий случай ведем сч-к времени ожидания, мало ли где он может понадобиться
if (MaxTimeOut <> INFINITE) //если не бесконечное ожидание
and (ActualTimeOut >= MaxTimeOut) then begin //и заданный тайм-аут исчерпан
ExitCode := ...; // код возврата, фиксирующий завершение потока по тайм-ауту для потенц.анализа причин завершения потока запустившим его кодом
Terminate;//тайм-аут исчерпан, терминируем сами себя
end;
end;
end;

If Terminated then
Exit;

if FTCP.Active then .... //и т.д.


Donal_Graeme   (2002-04-11 10:08:00) [40]


begin
FreeOnTerminate := False;
FTCP := TClientSocket.Create (nil);
FTCP.OnRead := TCPRead;
FTCP.OnConnect := TCPConnected;
FTCP.OnError := TCPError;
try
SC_ParseURL (URL, Proto, Host, Port, Path);//раскладываю урл на части
FTCP.Host := Host;
FTCP.Port := StrToInt (Port);
FTCP.ClientType := ctNonBlocking;
ResetEvent (hEvent);
FTCP.Open;
WaitForSingleObject (hEvent, 5000);// здесь ждёт сколько задано
If Terminated then Exit;
If FTCP.Active then // здесь Active = False в любом случае
begin
// по большому счёту этот кусок не важен, так как до него не доходит выполнение никогда
WaitHeaders := True;
Headers.Clear;
Output.Clear;
FTCP.Socket.SendText("GET " +"/" +Path +"HTTP/1.0"#13#10#13#10);
Repeat
Until Terminated;
end;
finally
FTCP.Close;
FTCP.Free;
end;
end;


FTCPError и FTCPConnected : SetEvent (hEvent);


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо