![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
TIdTcpServer [D7, WinXP]
Ozone © (2004-04-22 09:46:00)Как при обработке события OnExecute сделать синхронизацию?
Пишу так
procedure Test;
begin
{...}
end;
procedure TFServer.tcpServerExecute(AThread: TIdPeerThread);
begin
{...}
AThread.Synchronize(???);
{...}
end;
И нужно ли это, если при обработке данного события необходимо выполнять достаточно длинные по времени действия?
Всем спасибо.
Digitman (2004-04-22 14:38:00) [1]
> Я хочу через синхронайз вставить картинку в Image
совершенно необязательно использовать для этой цели Synchronize
создай экз-р TImage прямо в своем потоке, заполни его как тебе нужно, а далее посылай форме при помощи PostMessage некое сообщение, параметром которого передай ссылку на свой экз-р TImage
при получении формой сообщения бери параметр, приводи его к типу TImage и выполняй ImageНаФорме.Assign(переданный_Image), после чего не забудь разрушить переданный параметром объект Image
Ozone (2004-04-22 14:32:00) [2]TO Digitman © [26]
Спаасибо. Попробую.
Digitman (2004-04-22 14:30:00) [3]
> Пробовал так как задавал в вопросе - ошибку выдает
>
>
> AThread.Synchronize(Test);
ты хоть бы поинтересовался, О ЧЕМ КОНКРЕТНО говорит эта ошибка !
а говорит она о том, что Synchronize - защищенный метод класса TThread, и вызывать его допустимо только из методов наследников класса TThread (коим в дан.случае явл-ся TIdPeerThread)
ты же пытаешься вызвать защищенный метод отнюдь не не в методе класса TIdPeerThread, а в методе, являющемся обработчиком события OnExecute... обработчик же этот назначен у тебя, очевидно, как метод формы, на которую ты бросил IdTCPServer .. так что ж ты хочешь ?
для доступа к методу Synchronize ты должен создать класс-наследник TIdPeerThread, а чтобы можно было использовать экз-ры этого класса, ты должен написать и подключить собственный класс TIdThreadMgr
Ozone (2004-04-22 14:29:00) [4]TO Reindeer Moss Eater © [24]
>> Ну и зачем весь длинный Test выполнять через Syncronize?
Я не говорил, что Test длинный. Я хочу через синхронайз вставить картинку в Image.
>> Все клиентские подключения имеют дело с одним и тем же Image?
Дело обстоит немного сложнее. Есть 4 картинки (экрана), т.е. сразу могут транслировать только четыре клиента. НО! То куда они транслируют (Image) изменяется в режиме run-time (а точнее сам юзверь говорит кому и куда класть свою картинку).
Reindeer Moss Eater (2004-04-22 14:24:00) [5]Ну и зачем весьдлинный Test выполнять через Syncronize?
И еще.
Все клиентские подключения имеют дело с одним и тем же Image?
Ozone (2004-04-22 14:21:00) [6]TO Reindeer Moss Eater © [22], [23]
Все я прекрастно понимаю.
Просто, т.к. я не мог синхронизировать мои AThread потоки с основным VCL-потоком, то сделал КС на доступ к Image, вот и все.
Теперь хочу отказаться от КС и сделать по человечески.
Reindeer Moss Eater (2004-04-22 14:17:00) [7]А как именно вызвать эту самую синхронизацию?
Синхронизацию кого с чем? Можешь внятно сказать?
Reindeer Moss Eater (2004-04-22 14:15:00) [8]Ты хоть немного пробуешь понять что такое Syncronize и что такое критическая секция? А главное стокилометровую разницу между ними?
Ozone (2004-04-22 14:08:00) [9]TO Digitman © [10]
>> вот здесь, вероятно, syncronize() может и понадобиться
А как именно вызвать эту самую синхронизацию?
Пробовал так как задавал в вопросе - ошибку выдает
AThread.Synchronize(Test);
А если я это все заделаю через КС - будет ли это хорошим тоном?
Verg (2004-04-22 11:50:00) [10]
> Reindeer Moss Eater © (22.04.04 11:46) [18]
> Уж если ReadLN вызвал исключение то проверять соединение
> большого смысла нет.
> Можно смело заверщать обработку сессии клиента.
Не в этом дело, если остановка сервера произошла на readln, то и так все будет нормально.
А вот если это случилось на длительной (или зациклившейся) обработке принятой информации, при которой не производится проверки на целостность соединения, то как раз описываемый эффект и будет наблюдаться.
Reindeer Moss Eater (2004-04-22 11:46:00) [11]Уж если ReadLN вызвал исключение то проверять соединение большого смысла нет.
Можно смело заверщать обработку сессии клиента.
Verg (2004-04-22 11:38:00) [12]
> Reindeer Moss Eater © (22.04.04 11:23) [15]
> Проверяй-непроверяй, но если возврата из ReadLN нет, то
> что толку?
При остновке сервера, его поток отключает все клиентские сокеты и пытается остановить все клиентские потоки. При отключении соединения ReadLn даст исключение, которое будет обработано в TIdPeerThread.Run и приведет к остановке (завершению) клиентского потока.
Вот маленькая "модель":
Запустите сервер, потключитесь к его порту Telnet-ом и введите 15-20 сиволов плюс enter. После этого попытайтесь остановить сервер...
procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var S : string;
I : integer;
begin
S:=AThread.Connection.ReadLn;
for I:=1 to length(S) do
begin
S[I] := UpCase(S[I]);
Sleep(1000);
AThread.Connection.CheckForDisconnect; // Закометарив эту строку мы получим как раз Terminate Thread Timeout если попытаемся остановить сервер во время обработки строки клиентским потоком
end;
end;
Ozone (2004-04-22 11:37:00) [13]Хорошо, спасибо, попробую что-нить сделать.
И еще вопрос - может момно как-нибудь отловить исключение, возникающеся по истечению времени TimeOut'a?
Reindeer Moss Eater (2004-04-22 11:23:00) [14]Проверяй-непроверяй, но если возврата из ReadLN нет, то что толку?
Verg (2004-04-22 11:22:00) [15]
> Ozone © (22.04.04 11:16) [11]
Если в этом методе (tcpServerExecute) "закручивается" долгая оперция, например с циклом там или еще чего, то нужно хотя бы изредка проверять состояние соединеия по ходу выполнения этой операции.
Ozone (2004-04-22 11:21:00) [16]TO Reindeer Moss Eater ©[12]
А как этого избежать?
Reindeer Moss Eater (2004-04-22 11:19:00) [17]Твои методы чтения/записи выполняются с бесконечным таймаутом.
Вот и вся причина
Ozone (2004-04-22 11:16:00) [18]TO Digitman ©[9]
>> данная ошибка же возникает по совершенно иным причинам
Тогда не понятно почему - все остальное сделано вроде по аналогии с упомянутым выше примером???
Digitman (2004-04-22 11:12:00) [19]
> Ozone
конечно же, если ты влупил какой-то код в OnExecute в рамки синхронизации, то такая вот ситуация вполне может и иметь место : доп.поток ждет , когда указанный метод будет выполнен осн.потоком, а последний в этот момент (в обработчике, например, кнопки, где ты деактивируешь сервер) взвел Terminated и ждет, когда доп.поток завершится ..
получается замкнутый круг - "Ванька ждет Маньку, а Манька ждет Ваньку"
Digitman (2004-04-22 11:08:00) [20]
> <кое-что выводим на экран>
вот здесь, вероятно, syncronize() может и понадобиться
все остальное, скорей всего, обойдется безо всякой синхронизации
данная ошибка же возникает по совершенно иным причинам, никак не связанным с наличием или отсутствием синхронизации - период тайм-аута ожидания приема данных как минимум не должен быть INFINITE, иначе поток не сможет опрашивать флаг Terminated, взводимый сервером при принудительной его деактивации