Форум: "Основная";
Текущий архив: 2004.10.03;
Скачать: [xml.tar.bz2];
ВнизСинхронизация в потоке Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.065 c