Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.10.03;
Скачать: CL | DM;

Вниз

Синхронизация в потоке   Найти похожие ветки 

 
Fedia   (2004-09-15 10:11) [0]

Вопрос такой.
Есть две процедуры. Например


procedure Second(Label1: TLabel);
begin
 Label1.Caption:="тест";
end;

procedure First(Label1: TLabel);
begin
 Second(Label1);
end;


Процедура First вызывается в потоке:


procedure TSQLThrd.Execute;
begin
 First(Form1.Label1);  
end;


Без синхронизации не безопасно менять свойства визуальных компонентов. Как мне произвести синхронизацию изменения заголовка Label1?


 
Defunct ©   (2004-09-15 10:13) [1]

Synchronize F1


 
TUser ©   (2004-09-15 10:24) [2]

Да еще написать Form1.Label1, а то компилятор будет ругаться


 
Fedia   (2004-09-15 10:26) [3]

Ах ну конечно, как же я сразу не догадался :)
Если уж спрашиваю, так значит F1 мне не помог. Как сделать просто синхронизацию в Execute потока я разобрался, а вот как это сделать внутри вложенной процедуры не могу, к сожалению, нужна помощь.


 
Суслик ©   (2004-09-15 10:32) [4]


> к сожалению, нужна помощь.

для того, чтобы понять вопрос мне тоже нужна помошь, к сожалению.

Делаешь просто:
1) Выделяешь 10 минут времени.
2) Обдумываешь вопрос (что надо получить, что уже сделал и пр.).
3) Выделяешь еще 10 минут.
4) Аккуратно его записываешь.
5) Ждешь ответа.

Тебя удивит тот факт, что ты получишь нормальный и полезный ответ.
Проверь.


 
panov ©   (2004-09-15 10:38) [5]

>Fedia   (15.09.04 10:11)
Вот вчера писал, разбери пример и поймешь.


unit uSimpleTimer;

interface

uses
 Classes,windows;

type
 TProcTimer = procedure;
 TSimpleTimer = class(TThread)
 private
   FCS: RTL_CRITICAL_SECTION;
   FInterval: Integer;
   FOnTimer: TProcTimer;
   procedure FTimer;
   procedure SetOnTimer(Proc: TProcTimer);
 protected
   procedure Execute; override;
 public
   constructor Create(const aInterval: Integer);
   destructor Destroy;override;
   procedure Timer;
   property OnTimer: TProcTimer write SetOnTimer;
   procedure Start;
   procedure Stop;
   procedure Release;
 end;

implementation

procedure TSimpleTimer.Release;
begin
 Terminate;
 Resume;
end;

destructor TSimpleTimer.Destroy;
begin
end;

constructor TSimpleTimer.Create(const aInterval: Integer);
begin
 inherited Create(True);
 FreeOnTerminate := True;
 FInterval := aInterval;
end;

procedure TSimpleTimer.Start;
begin
 Resume;
end;

procedure TSimpleTimer.Stop;
begin
 Suspend;
end;

procedure TSimpleTimer.SetOnTimer(Proc: TProcTimer);
begin
 FOnTimer := Proc;
end;

procedure TSimpleTimer.Timer;
begin
 FOnTimer;
end;

procedure TSimpleTimer.FTimer;
begin
 if Assigned(FOnTimer) then
 begin
   EnterCriticalSection(FCS);
   FOnTimer;
   LeaveCriticalSection(FCS);
 end;
end;

procedure TSimpleTimer.Execute;
begin
 InitializeCriticalSection(FCS);
 try
   while not Terminated do
   begin
     Sleep(FInterval);
     if Terminated then Continue;
     FTimer;
   end;
 finally
   DeleteCriticalSection(FCS);
 end;
end;

end.


Вызов:


procedure MyOnTimer;
begin
 fMain.sbMain.Panels[0].Text := FormatDateTime("dd.mm.yyyy hh:nn:ss",now);
end;

procedure TfMain.FormCreate(Sender: TObject);
begin
 ST := TSimpleTimer.Create(1000);
 ST.OnTimer := MyOnTimer;
 ST.Timer;
 ST.Start;
end;

procedure TfMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 ST.Release;
end;



 
Erik1 ©   (2004-09-15 10:57) [6]

To panov
Чегото я синхронизации невижу?


 
panov ©   (2004-09-15 10:59) [7]

>Erik1 ©   (15.09.04 10:57) [6]
см. procedure TSimpleTimer.FTimer;


 
Erik1 ©   (2004-09-15 11:15) [8]

И как соотносится вход и выход в критическую секцию с синхнонизацией главного потока? При выполнении этого кода возможна ошибка. Cнхнонизация делается с использованием Synchronize или PostMessage.


 
TUser ©   (2004-09-15 11:17) [9]

Если хочешь через Synchr, не прописывая явно критические секции - то он вызывается из любого метода потока, который м.б. вызван из Execute. Особой разницы в его использовании нет. Другой вопрос - если все написано как у тебя в топике, т.к. First и Second - просто процедуры, а не методы класса. Они тогда ничего не знают про Synchronize, т.к. этот метод - из TThtread"а. Сделай их методами, и все будет хорошо.

PS. Интересно, я угадал в чем проблема?


 
TUser ©   (2004-09-15 11:21) [10]


> Erik1 ©   (15.09.04 11:15) [8]

S сам использует критические секции.


 
panov ©   (2004-09-15 11:27) [11]

>Erik1 ©   (15.09.04 11:15) [8]
Посмотри исходный код Synchronize


 
Fedia   (2004-09-15 11:40) [12]

Я тут погрузился в разбор кода и был временно не доступен :)
TUser ©   (15.09.04 11:17) [9]
>> PS. Интересно, я угадал в чем проблема?
Мне интересно о чем тут было гадать? Хотя похоже ты не один гадал, следовательно косяк мой.
Я не могу переделывать все процедуры в методы потока. Слишком много кода придется менять. Поэтому хотел изобрести хитрую ссылку на  Synchronize, чтобы заменить все строки типа:
Label1.Caption:="новый заголовок" на например
MySync(Label1, "новый заголовок"), где MySync - процедура, в которой происходит синхронизация.

А на счет входа в критические секции сейчас попробую часть кода переделать и запустить на ночное тестирование. Если не упадет, переделаю остальное.


 
panov ©   (2004-09-15 11:45) [13]

>All
Код [5] некорректен, так как эту критическую секцию должны использовать все потоки при обращении к VCL.


 
Erik1 ©   (2004-09-15 15:11) [14]

To panov
С этим полностью согласен, добавлю, что во все входит и главный поток.

To TUser
Ты сам смотрел Synchronize? Незаметил случайно вот такю строку SendMessage(ThreadWindow, CM_EXECPROC, 0, Longint(Self)) ? В Synchronize посылается сообщение созданому окну, а в обработчике сообщений ищется CM_EXECPROC и вызывается нужный метод. Поэтому Synchronize просто использует очередь сообщенией для синхронизации.


 
Fedia   (2004-09-16 01:28) [15]

Все, сделал, заработало.
Слава Богу я тут на предприятии не один программистом работаю, и один из сотрудников предприятия подсказал как сделать.
В раздел protected потока я добавил экземпляры визуальных компонентов, свойства которых необходимо менять в потоке, а также переменные, символизирующие меняемые свойства.

 TSQLThrd2 = class(TThread)
 protected
   Label1: TLabel;
   LCaption: String;
   PB: TGaugeCX; //это видоизмененный ProgressBar
   Position: Integer;
 public
   procedure ChengLabel;
   procedure ChangePB;
 end;

var
 TSQLThrd: TSQLThrd2;


Процедуры, в которых происходит изменение свойств визуальных компонентов

procedure TSQLThrd2.ChengLabel;
begin
 Label1.Caption:=LCaption;
end;

procedure TSQLThrd2.ChangePB;
begin
 PB.Position:=Position;
end;

Процедуры, в которых происходит синхронизация с основным потоком:

procedure MyLabelSynchronize(Label1: TLabel; s: String);
begin
 TSQLThrd.Label1:=Label1;
 TSQLThrd.LCaption:=s;
 TSQLThrd.Synchronize(TSQLThrd, TSQLThrd.ChengLabel);
end;

procedure MyPBSynchronize(PB: TGaugeCX; i: Integer);
begin
 TSQLThrd.PB:=PB;
 TSQLThrd.Position:=i;
 TSQLThrd.Synchronize(TSQLThrd, TSQLThrd.ChangePB);
end;


А вот замена процедуры Second из (15.09.04 10:11):  

procedure Second(Label1: TLabel);
begin
 //Label1.Caption:="тест"; //без синхронизации
 MyLabelSynchronize(Label1, "тест"); //с использованием синхронизации
end;



Страницы: 1 вся ветка

Текущий архив: 2004.10.03;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.025 c
4-1093250479
Adolph
2004-08-23 12:41
2004.10.03
CreateWindow


14-1094898365
Pat
2004-09-11 14:26
2004.10.03
Выбор языка для нового проекта


8-1088677157
leonidus
2004-07-01 14:19
2004.10.03
Как извлечь информацию из ID тэгов mp3-файлов


14-1095374250
KilkennyCat
2004-09-17 02:37
2004.10.03
Что лучше, Си или Паскаль?


14-1094763527
Palladin
2004-09-10 00:58
2004.10.03
Посоветуйте смартфон...