![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
TClientSocket в TThread не работает... [D6, Win95/98]
Donal_Graeme © (2002-04-10 18:09:00)ничего не понимаю...
в главной форме работает, внутри метода потока Execute - не работает. один и тот же код :
FTCP.Host := Host;
FTCP.Port := StrToInt (Port);
FTCP.ClientType := ctNonBlocking;
FTCP.Open;
если в потоке, то работает так:
если Host задать неправильно, то он вываливается с ошибкой, т.е. работает, а если Host задан правильно, то коннекта не происходит и ошибок тоже не возникает.
хотя в основной программе коннектится и нормально работает.
Vlad___ (2002-04-19 13:36:00) [1]Народ - у TClientSocket есть свой хэндл окна который выделяется при создании сокета и через этот хэндл сокет получает все события, и если сокет создавать динамически в потоке + работать в неблокирующем режиме то просто необходимо в этом потоке выбирать сообщения для сокета и диспатчить эти сообщения - заодно можно избежать "Async Lookup ..." ошибки (не передавая это сообщение сокету), которая не вызывает OnError и вызывает exception. Заодно по GetMessage поток тормозится и ждет событий.
Donal_Graeme (2002-04-12 14:47:00) [2]кажется, понял :-) большое спасибо за помощь
Digitman (2002-04-12 10:36:00) [3]>Donal_Graeme
Использование TClientSocket в режиме ctNonBlocking в доп.потоке является концептуально неправильным решением. Хотя и можно добиться корректной работы гнезда при таком подходе (см. выше примеры с уточнениями), все же лучше в твоем случае работать в режиме ctBlocking.
Reindeer Moss Eater (2002-04-12 10:11:00) [4]Видимо потому что это событие генерится до возврата из метода DoOpen.
Иными словами до вызова функции ожидания
Donal_Graeme (2002-04-12 09:57:00) [5]а почему тогда OnError обрабатывается?
в чём разница между OnError и OnConnect?
Reindeer Moss Eater (2002-04-12 08:48:00) [6]Признаю, что вчера был неправ насчет вторичных потоков в TClientSocket.
Их действительно нет.
Вся реализация асинхронных методов находится внутри winsock.dll
Если режим работы асинхронный, то класс просто сообщает что хочет выполнить метод асинхронно и передает дескриптор окна, которому winsock.dll должна будет отправить сообщение по окончании метода.
После чего генерится событие внутри класса.
Но так как нитка спит, то сообщение не обрабатывается.
Digitman (2002-04-12 08:38:00) [7]>Reindeer Moss Eater
Ты уже близок к истине)
Вот смотри. Дело не в том, что поток "спит", а в том, что в "спать" ему в дан.случае следует чуть по-другому. Доработаем немного цикл ожидания и заставим доп.поток "спать чутко", реагируя на оконные события:
var
Msg: TMsg;
...
PeekMessage(Msg, 0, WM_USER, WM_USER, PM_NOREMOVE);//первая строчка в Execute()
...
while not Terminated do
case MsgWaitForMultipleObjects (1, hEvent, False, CyclicTimeOut, QS_ALLINPUT) of
WAIT_OBJECT_0: break; // hEvent просигналил
WAIT_TIMEOUT:
begin
Inc(ActualTimeOut, CyclicTimeOut);
if (MaxTimeOut <> INFINITE)
and (ActualTimeOut >= MaxTimeOut) then begin
ExitCode := ...;
Terminate;
end;
end;
WAIT_OBJECT_0 + 1:
while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
if Msg.hWnd = 0 then
Dispatch(Msg.Message)
else
DispatchMessage(Msg);
end;
...
Reindeer Moss Eater (2002-04-11 18:47:00) [8]>Digitman
Если помнишь, я сказал, что проблема автора не в его коде, а в реализации асинхронного метода в классе TClientSocket.
Если поток, создавший экземпляр TClientSocket спит, то экземпляр TClientSocket не генерирует события OnConnect.
Автор проверил это в основном потоке и уже сказал, что не работает не только в дополнительной нитке, но и в основной, если в ней вызвать функцию ожидания.
Digitman (2002-04-11 18:38:00) [9]>Reindeer Moss Eater
Вызов Sendmessage() предназначен для синхронной посылки сообщения не потоку, а окну.
Доп.поток у автора нигде не вызывает Synchronize() - ни явно ни неявно.
Reindeer Moss Eater (2002-04-11 17:43:00) [10]Я конечно же был неточен, согласен.
Но если вторичный поток использует syncronize, или делает Sendmessage вызвавшему потоку, то получится как раз то, что я и имел ввиду
Digitman (2002-04-11 17:16:00) [11]>Reindeer Moss Eater
Утверждение твое неверно. Совершенно неверно. Кодовые потоки в контексте одного процесса абсолютно независимы друг от друга и выполняются "параллельно". Иначе бы понятия "синхронизация потоков" и "объекты синхронизации" попросту были бы лишены всякого смысла применительно к рассматриваемой нами ситуации.
Когда некий кодовый поток (неважно - основной он в процессе или дополнительный) вызывает ф-цию ожидания событий, это никаким образом не влияет на другие потоки процесса (которые могут вообще ничего не знать про существование того самого, "заснувшего"), за исключением разве что оперативного перераспределения системой "освободившихся" квантов времени между прочими "бодрствующими" потоками процесса.
Reindeer Moss Eater (2002-04-11 16:31:00) [12]>Digitman
И это тоже может быть.
Только многопоточность в Delphi реализована таким образом, что код вторичного потока в конечном итоге все равно выполняется в основном потоке.
И если в последнем вызвана функция ожидания, то вторичный поток тоже стоит на месте.
Я был когда-то сильно опечален, поняв это.
Digitman (2002-04-11 16:25:00) [13]>Reindeer Moss Eater
Есть очередь сообщений окну, а есть очередь сообщений потоку (дополнительному). Две совершенно разные очереди, с т.з. ОС и API-вызовов, позволяющих реагировать на эти сообщения
Reindeer Moss Eater (2002-04-11 16:14:00) [14]>Digitman
Повторю еще раз, что я здесь говорил про КЛАССЫ VCL
И класc TClientSocket(как и любой другой класс) если у него есть АСИНХРОННЫЙ метод
НЕ МОЖЕТ НЕ ИМЕТЬ внутри себя "внутренних потоков"
Donal_Graeme (2002-04-11 16:11:00) [15]я имею ввиду - если использовать WaitForSingleObject
Donal_Graeme (2002-04-11 16:08:00) [16]я попробовал... точно, врежиме nonBlocking в основном потоке OnConnect тоже не ловится.
Digitman (2002-04-11 16:07:00) [17]>Reindeer Moss Eater
Нет никаких "внутренних потоков" у гнезда - объекта ОС.
Как нет их и в гнезде - объекте VCL класса TClientSocket ни в ctBlocking- ни в ctNonBlocking-режиме.
Reindeer Moss Eater (2002-04-11 16:02:00) [18]> Digitman
Попробуй в основном потоке сделать Waitforsingleobject и после этого посмотри как Win32 будет "автоматически вызывать оконную функцию"
Reindeer Moss Eater (2002-04-11 15:58:00) [19]ctBlocking работает патаму что не использует поток внутри класса.
Reindeer Moss Eater (2002-04-11 15:55:00) [20]> Donal_Graeme
Я не изучал код класа TClientSocket, но могу предположить что событие OnError генерится не внутри потока, создаваемого в классе сокета.
Но если режим асинхронный, то событие OnConnect генерится именно из этого потока (не может по другому быть).
А раз поток, создавний экземпляр TClientSocket "спит", то сообщения того "внутреннего" потока (который так не понравился Digitman"у) просто некому обрабатывать.
Вот и все.
Выход простой: либо жди event в цикле со слипами, либо используй синхронный режим.
Асинронный режим удобен именно в основном потоке приложения, а в доплнительных потоках от него никакого толку нет.