Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 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.54 MB
Время: 0.038 c
14-1085642709
YurikGl
2004-05-27 11:25
2004.06.13
Опять форум тормозит... :(


14-1085410435
SPeller
2004-05-24 18:53
2004.06.13
Не пейте за рулём.


3-1085031404
Vogul
2004-05-20 09:36
2004.06.13
Отображение больших объемов данных в Dataset


8-1081078391
NV-VETAL
2004-04-04 15:33
2004.06.13
Сравнение произнесенной речи. Помогите!


14-1085468028
*Pavel
2004-05-25 10:53
2004.06.13
Международные платежные системы