Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2004.06.13;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.041 c
14-1085504090
Ilya__
2004-05-25 20:54
2004.06.13
Можно ли так делать ?


1-1085724426
CyberSpy
2004-05-28 10:07
2004.06.13
Child


1-1085778202
Talle
2004-05-29 01:03
2004.06.13
Динамический массив


14-1085575633
AlexG
2004-05-26 16:47
2004.06.13
Давайте разберемся....


3-1084366877
Desdechado
2004-05-12 17:01
2004.06.13
странное поведение связки SQLQuery-DatasetProvider-ClientDataset





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский