Текущий архив: 2004.06.13;
Скачать: CL | DM;
ВнизTIdTcpServer Найти похожие ветки
← →
Ozone © (2004-04-22 09:46) [0]Как при обработке события OnExecute сделать синхронизацию?
Пишу так
procedure Test;
begin
{...}
end;
procedure TFServer.tcpServerExecute(AThread: TIdPeerThread);
begin
{...}
AThread.Synchronize(???);
{...}
end;
И нужно ли это, если при обработке данного события необходимо выполнять достаточно длинные по времени действия?
Всем спасибо.
← →
Reindeer Moss Eater © (2004-04-22 09:48) [1]Не нужно
← →
Ozone © (2004-04-22 10:39) [2]TO Reindeer Moss Eater © [1]
А можешь обьяснить почему?
← →
Reindeer Moss Eater © (2004-04-22 10:42) [3]Могу.
А ты можешь сказать зачем тебе здесь метод Syncronyze?
Просто так, для мебели?
← →
Verg © (2004-04-22 10:42) [4]
> И нужно ли это, если при обработке данного события необходимо
> выполнять достаточно длинные по времени действия?
Применение Synchronize никак не связано с "длинной по времени" выполняемых в этом методе действий.
Synchronize нужно применять для действий с потоконебезопасными объектами, такими как, например, визуальные оъекты VCL.
← →
Reindeer Moss Eater © (2004-04-22 10:48) [5]Причем даже если нужен доступ к потоконебезопасным VCL, то все равно можно обойтись без этого метода Synchronize
← →
Reindeer Moss Eater © (2004-04-22 10:54) [6]Скорее всего твой код должен быть похож на следующий
procedure TFServer.Test(AThread: TIdPeerThread);
begin
DoSomething;
DoSomethingElse;
AThread.Connection.Writeln("Test");
end;
procedure TFServer.tcpServerExecute(AThread: TIdPeerThread);
begin
{...}
Test(AThread)
{...}
end;
← →
Ozone © (2004-04-22 11:00) [7]У меня в обработчике стоит что-то типа того:
< читаем строку >
< читаем Stream >
<сохраняем в файл>
<сохранияем в БД>
<кое-что выводим на экран>
<принимаем строку>
Все это нормально работает до того момента, когда я принуддительно не закрою сервер когда к нему еще подключены клиенты (выдает "Terminate Thread Timeout")
PS: У меня в обработчике стоит что-то типа того:
< читаем строку >
< читаем Stream >
<сохраняем в файл>
<сохранияем в БД>
<кое-что выводим на экран>
<принимаем строку>
Все это нормально работает до того момента, когда я принуддительно не закрою сервер когда к нему еще подключены клиенты (выдает "Terminate Thread Timeout")
PS: подключение клиентов делал по аналогии в примером "IdTCPDemo"
Как решить проблему?
← →
Ozone © (2004-04-22 11:04) [8]Сорри за баг с мессагой.
← →
Digitman © (2004-04-22 11:08) [9]
> <кое-что выводим на экран>
вот здесь, вероятно, syncronize() может и понадобиться
все остальное, скорей всего, обойдется безо всякой синхронизации
данная ошибка же возникает по совершенно иным причинам, никак не связанным с наличием или отсутствием синхронизации - период тайм-аута ожидания приема данных как минимум не должен быть INFINITE, иначе поток не сможет опрашивать флаг Terminated, взводимый сервером при принудительной его деактивации
← →
Digitman © (2004-04-22 11:12) [10]
> Ozone
конечно же, если ты влупил какой-то код в OnExecute в рамки синхронизации, то такая вот ситуация вполне может и иметь место : доп.поток ждет , когда указанный метод будет выполнен осн.потоком, а последний в этот момент (в обработчике, например, кнопки, где ты деактивируешь сервер) взвел Terminated и ждет, когда доп.поток завершится ..
получается замкнутый круг - "Ванька ждет Маньку, а Манька ждет Ваньку"
← →
Ozone © (2004-04-22 11:16) [11]TO Digitman ©[9]
>> данная ошибка же возникает по совершенно иным причинам
Тогда не понятно почему - все остальное сделано вроде по аналогии с упомянутым выше примером???
← →
Reindeer Moss Eater © (2004-04-22 11:19) [12]Твои методы чтения/записи выполняются с бесконечным таймаутом.
Вот и вся причина
← →
Ozone © (2004-04-22 11:21) [13]TO Reindeer Moss Eater ©[12]
А как этого избежать?
← →
Verg © (2004-04-22 11:22) [14]
> Ozone © (22.04.04 11:16) [11]
Если в этом методе (tcpServerExecute) "закручивается" долгая оперция, например с циклом там или еще чего, то нужно хотя бы изредка проверять состояние соединеия по ходу выполнения этой операции.
← →
Reindeer Moss Eater © (2004-04-22 11:23) [15]Проверяй-непроверяй, но если возврата из ReadLN нет, то что толку?
← →
Ozone © (2004-04-22 11:37) [16]Хорошо, спасибо, попробую что-нить сделать.
И еще вопрос - может момно как-нибудь отловить исключение, возникающеся по истечению времени TimeOut"a?
← →
Verg © (2004-04-22 11:38) [17]
> 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;
← →
Reindeer Moss Eater © (2004-04-22 11:46) [18]Уж если ReadLN вызвал исключение то проверять соединение большого смысла нет.
Можно смело заверщать обработку сессии клиента.
← →
Verg © (2004-04-22 11:50) [19]
> Reindeer Moss Eater © (22.04.04 11:46) [18]
> Уж если ReadLN вызвал исключение то проверять соединение
> большого смысла нет.
> Можно смело заверщать обработку сессии клиента.
Не в этом дело, если остановка сервера произошла на readln, то и так все будет нормально.
А вот если это случилось на длительной (или зациклившейся) обработке принятой информации, при которой не производится проверки на целостность соединения, то как раз описываемый эффект и будет наблюдаться.
← →
Ozone © (2004-04-22 14:08) [20]TO Digitman © [10]
>> вот здесь, вероятно, syncronize() может и понадобиться
А как именно вызвать эту самую синхронизацию?
Пробовал так как задавал в вопросе - ошибку выдает
AThread.Synchronize(Test);
А если я это все заделаю через КС - будет ли это хорошим тоном?
← →
Reindeer Moss Eater © (2004-04-22 14:15) [21]Ты хоть немного пробуешь понять что такое Syncronize и что такое критическая секция? А главное стокилометровую разницу между ними?
← →
Reindeer Moss Eater © (2004-04-22 14:17) [22]А как именно вызвать эту самую синхронизацию?
Синхронизацию кого с чем? Можешь внятно сказать?
← →
Ozone © (2004-04-22 14:21) [23]TO Reindeer Moss Eater © [22], [23]
Все я прекрастно понимаю.
Просто, т.к. я не мог синхронизировать мои AThread потоки с основным VCL-потоком, то сделал КС на доступ к Image, вот и все.
Теперь хочу отказаться от КС и сделать по человечески.
← →
Reindeer Moss Eater © (2004-04-22 14:24) [24]Ну и зачем весь длинный Test выполнять через Syncronize?
И еще.
Все клиентские подключения имеют дело с одним и тем же Image?
← →
Ozone © (2004-04-22 14:29) [25]TO Reindeer Moss Eater © [24]
>> Ну и зачем весь длинный Test выполнять через Syncronize?
Я не говорил, что Test длинный. Я хочу через синхронайз вставить картинку в Image.
>> Все клиентские подключения имеют дело с одним и тем же Image?
Дело обстоит немного сложнее. Есть 4 картинки (экрана), т.е. сразу могут транслировать только четыре клиента. НО! То куда они транслируют (Image) изменяется в режиме run-time (а точнее сам юзверь говорит кому и куда класть свою картинку).
← →
Digitman © (2004-04-22 14:30) [26]
> Пробовал так как задавал в вопросе - ошибку выдает
>
>
> AThread.Synchronize(Test);
ты хоть бы поинтересовался, О ЧЕМ КОНКРЕТНО говорит эта ошибка !
а говорит она о том, что Synchronize - защищенный метод класса TThread, и вызывать его допустимо только из методов наследников класса TThread (коим в дан.случае явл-ся TIdPeerThread)
ты же пытаешься вызвать защищенный метод отнюдь не не в методе класса TIdPeerThread, а в методе, являющемся обработчиком события OnExecute... обработчик же этот назначен у тебя, очевидно, как метод формы, на которую ты бросил IdTCPServer .. так что ж ты хочешь ?
для доступа к методу Synchronize ты должен создать класс-наследник TIdPeerThread, а чтобы можно было использовать экз-ры этого класса, ты должен написать и подключить собственный класс TIdThreadMgr
← →
Ozone © (2004-04-22 14:32) [27]TO Digitman © [26]
Спаасибо. Попробую.
← →
Digitman © (2004-04-22 14:38) [28]
> Я хочу через синхронайз вставить картинку в Image
совершенно необязательно использовать для этой цели Synchronize
создай экз-р TImage прямо в своем потоке, заполни его как тебе нужно, а далее посылай форме при помощи PostMessage некое сообщение, параметром которого передай ссылку на свой экз-р TImage
при получении формой сообщения бери параметр, приводи его к типу TImage и выполняй ImageНаФорме.Assign(переданный_Image), после чего не забудь разрушить переданный параметром объект Image
Страницы: 1 вся ветка
Текущий архив: 2004.06.13;
Скачать: CL | DM;
Память: 0.52 MB
Время: 0.036 c