![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Синхронизация в потоке [D7, Win2k]
Fedia © (2004-09-15 10:11:00)Вопрос такой.
Есть две процедуры. Например
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?
Fedia (2004-09-16 01:28:00) [1]Все, сделал, заработало.
Слава Богу я тут на предприятии не один программистом работаю, и один из сотрудников предприятия подсказал как сделать.
В раздел 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;
Erik1 (2004-09-15 15:11:00) [2]To panov
С этим полностью согласен, добавлю, что во все входит и главный поток.
To TUser
Ты сам смотрел Synchronize? Незаметил случайно вот такю строку SendMessage(ThreadWindow, CM_EXECPROC, 0, Longint(Self)) ? В Synchronize посылается сообщение созданому окну, а в обработчике сообщений ищется CM_EXECPROC и вызывается нужный метод. Поэтому Synchronize просто использует очередь сообщенией для синхронизации.
panov (2004-09-15 11:45:00) [3]>All
Код [5] некорректен, так как эту критическую секцию должны использовать все потоки при обращении к VCL.
Fedia (2004-09-15 11:40:00) [4]Я тут погрузился в разбор кода и был временно не доступен :)
TUser © (15.09.04 11:17) [9]
>> PS. Интересно, я угадал в чем проблема?
Мне интересно о чем тут было гадать? Хотя похоже ты не один гадал, следовательно косяк мой.
Я не могу переделывать все процедуры в методы потока. Слишком много кода придется менять. Поэтому хотел изобрести хитрую ссылку на Synchronize, чтобы заменить все строки типа:
Label1.Caption:='новый заголовок' на например
MySync(Label1, 'новый заголовок'), где MySync - процедура, в которой происходит синхронизация.
А на счет входа в критические секции сейчас попробую часть кода переделать и запустить на ночное тестирование. Если не упадет, переделаю остальное.
panov (2004-09-15 11:27:00) [5]>Erik1 © (15.09.04 11:15) [8]
Посмотри исходный код Synchronize
TUser (2004-09-15 11:21:00) [6]
> Erik1 © (15.09.04 11:15) [8]
S сам использует критические секции.
TUser (2004-09-15 11:17:00) [7]Если хочешь через Synchr, не прописывая явно критические секции - то он вызывается из любого метода потока, который м.б. вызван из Execute. Особой разницы в его использовании нет. Другой вопрос - если все написано как у тебя в топике, т.к. First и Second - просто процедуры, а не методы класса. Они тогда ничего не знают про Synchronize, т.к. этот метод - из TThtread'а. Сделай их методами, и все будет хорошо.
PS. Интересно, я угадал в чем проблема?
Erik1 (2004-09-15 11:15:00) [8]И как соотносится вход и выход в критическую секцию с синхнонизацией главного потока? При выполнении этого кода возможна ошибка. Cнхнонизация делается с использованием Synchronize или PostMessage.
panov (2004-09-15 10:59:00) [9]>Erik1 © (15.09.04 10:57) [6]
см.procedure TSimpleTimer.FTimer;
Erik1 (2004-09-15 10:57:00) [10]To panov
Чегото я синхронизации невижу?
panov (2004-09-15 10:38:00) [11]>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;
Суслик (2004-09-15 10:32:00) [12]
> к сожалению, нужна помощь.
для того, чтобы понять вопрос мне тоже нужна помошь, к сожалению.
Делаешь просто:
1) Выделяешь 10 минут времени.
2) Обдумываешь вопрос (что надо получить, что уже сделал и пр.).
3) Выделяешь еще 10 минут.
4) Аккуратно его записываешь.
5) Ждешь ответа.
Тебя удивит тот факт, что ты получишь нормальный и полезный ответ.
Проверь.
Fedia (2004-09-15 10:26:00) [13]Ах ну конечно, как же я сразу не догадался :)
Если уж спрашиваю, так значит F1 мне не помог. Как сделать просто синхронизацию в Execute потока я разобрался, а вот как это сделать внутри вложенной процедуры не могу, к сожалению, нужна помощь.
TUser (2004-09-15 10:24:00) [14]Да еще написать Form1.Label1, а то компилятор будет ругаться
Defunct (2004-09-15 10:13:00) [15]Synchronize F1