![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
В потоке не вызывается событие ttimer (запутался в потоках) [D7, WinXP]
msgipss © (2005-09-15 12:06:00)Здравствуйте знатоки, помогите пожалуйста понять ситуацию,
Есть тестовая форма, на ней кнопка, по кнопке создаю, запускаю Thread, в этом Thread'е создаю запускаю еще 1 Thread, в последнем треде есть ttimer, так вот событие этого таймера не могу получить, не срабоатывает оно, в первом пробовал - срабатывает без проблем.
msgipss (2005-09-16 07:41:00) [1]Defunct:
я ttimer не использую, время считаю сам (можно и так как у Вас),
ttimer попробовал - не получилось, стало любопытно - начал задавать глупые вопросы, ответы получил (спасибо участникам ветки) закрепил теорией - теперь довольный 8)
Defunct (2005-09-16 06:30:00) [2]господа..вчастности msgipss...
если вопрос только в таймере, то почему бы вместо TTimer не воспользоватья функцией GetTickCount либо в крайнем случае функцией Now..
Thread1 = class(TThread)
private
fEventTime : Cardinal;
function SetTimer( const Interval:Cardinal);
procedure ItMustBeSynchronized;
protected
procedure Execute; override; // Основной метод потока
procedure SomeEvent(Sender: TObject); // обработка таймера выполнения события
end;
procedure Thread1.SetTimer;
begin
fEventTime := GetTickCount + Interval;
end;
procedure Thread1.Execute;
begin
SetTimer( 3000 );
while not Terminated do
begin
sleep(100);
if GetTickCount > fEventInterval then
begin
SomeEvent( Self );
SetTimer( 3000 );
end;
end;
end;
procedure Thread1.ItMustBeSynchronized;
begin
ShowMessage( 'Thread1' );
end;
procedure Thread1.SomeEvent(Sender: TObject); // обработка таймера выполнения события
begin
Synchronize( ItMustBeSynchronized );
end;
msgipss (2005-09-16 06:12:00) [3]Digitman, спасибо - сел в отладку с книжкой 8)
Digitman (2005-09-15 15:09:00) [4]вру ..
while not Terminated do
begin
if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
DispatchMessage(Msg);
sleep(1);
end;
Digitman (2005-09-15 15:07:00) [5]
> msgipss (15.09.05 14:44) [10]
> как можно обработать событие, например на выше указанном
> тесте?
обычным образом :
procedure ThreadN.Execute;
var
Msg: TMsg;
begin
try
dTimer := TTimer.Create(nil);
try
dTimer.OnTimer:=OnTimerClose;
dTimer.Interval:=3000;
dTimer.Enabled:=true;
while not Terminated and PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
begin
DispatchMessage(Msg);
sleep(1);
end;
finally
dTimer.Free;
end;
except
on e: exception do
MessageBox(0, PChar(e.Classname + ' ' e.Message), PChar('Исключительная ситуация в объекте-потоке класса ' + Self.ClassName), mb_ok or mb_setforeground);
end;
end;
procedure ThreadN.OnTimerClose(Sender: TObject);
var
s: String;
begin
s := 'Инициатор события - объект класса ' + Sender.ClassName;
if GetCurrentThreadId = MainThreadId then
showmessage(s)
else
MessageBox(0, PChar(s), '', mb_ok or mb_setforeground);
if Sender is TThread then
TThread(Sender).Terminate;
end;
Reindeer Moss Eater (2005-09-15 14:57:00) [6]>не совсем так, пока таймер не натикал исполняется другая логика..
Если что-то выполняется, пока таймер не тикает, то значит можно выполнить и что-то еще и другое пока таймер не тикает.
Отсюда вывод - таймер не нужен.
msgipss (2005-09-15 14:44:00) [7]Reindeer Moss Eater: Что делает поток когда ждет тики таймера?
не совсем так, пока таймер не натикал исполняется другая логика..
Digitman © а тогда не скромный вопрос - как можно обработать событие, например на выше указанном тесте?
Digitman (2005-09-15 14:24:00) [8]
> как запустить таймер в контексте самого потока
создатьи запуститьобъект-таймер в теле метода Execute() того самого потока, который заинтересован в событиях этого таймера.
> с обработкой будут проблемы
любые проблемы решаемы.
> или обрабатывать через основной - да ?
нет.
основной ответственен ТОЛЬКО за обработку событий тех таймеров. который созданы в его контексте
в общем же случае тот поток, который создал объект-таймер, является ответственным за ожидание и обработку событий этого таймера ... никто за него это не сделает
Reindeer Moss Eater (2005-09-15 14:21:00) [9]Что делает поток когда ждет тики таймера?
Ничего не делает.
Отсюда вывод, что пока таймер не натикал нужное кол-во времени - поток не нужен вообще.
msgipss (2005-09-15 14:15:00) [10]запустить то можно вот с обработкой будут проблемы, или обрабатывать через основной - да ?,
буду убирать таймеры - считать время ручками
msgipss (2005-09-15 13:59:00) [11]Smithson: А зачем в потоке таймер? Объясни плиз.
иногда нужно менять логику потока через опр.врем.интервал,
согласен можно и без таймера..
Digitman ©: этот таймер создан в контексте доп.потока 1, который никак не обрабатывает сообщения окну созданного в нем таймера
а как запустить таймер в контексте самого потока, если первый поток создает несколько десятков вторых ?
Digitman (2005-09-15 13:44:00) [12]constructor Thread2.Create(bStart:Boolean); // Пишем свой конструктор Create
begin
..
dTimer:= TTimer.Create(nil); //этот таймер создан в контексте доп.потока 1, который никак не обрабатывает сообщения окну созданного в нем таймера
..
end;
Smithson (2005-09-15 13:32:00) [13]А зачем в потоке таймер? Объясни плиз.
msgipss (2005-09-15 12:51:00) [14]разрешите вам показать пример кода, Digitman только сильно не бей:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
Thread2 = class(TThread)
private
dTimer: TTimer;
protected
procedure Execute; override; // Основной метод потока
procedure OnTimerClose(Sender: TObject); // обработка таймера выполнения события
public
constructor Create(bStart:Boolean); // Пишем свой конструктор Create
end;
Thread1 = class(TThread)
private
dTimer: TTimer;
thread:thread2;
protected
procedure Execute; override; // Основной метод потока
procedure OnTimerClose(Sender: TObject); // обработка таймера выполнения события
public
constructor Create(bStart:Boolean); // Пишем свой конструктор Create
end;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
thread:Thread1;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
constructor Thread1.Create(bStart:Boolean); // Пишем свой конструктор Create
begin
FreeOnTerminate := true; // После завершения выполнения метода Execute разрушать объект потока
dTimer:= TTimer.Create(nil);
if bStart then inherited Create(False) // создать задачу и сразу запустить
else inherited Create(True); // создать приостановленную задачу
end;
procedure Thread1.Execute;
begin
thread:=Thread2.Create(true);
dTimer.OnTimer:=OnTimerClose;
dTimer.Interval:=3000;
dTimer.Enabled:=true;
while not Terminated do
begin
sleep(1000);
end;
end;
procedure Thread1.OnTimerClose(Sender: TObject); // обработка таймера выполнения события
begin
showmessage('Thread 1');
end;
constructor Thread2.Create(bStart:Boolean); // Пишем свой конструктор Create
begin
FreeOnTerminate := true; // После завершения выполнения метода Execute разрушать объект потока
dTimer:= TTimer.Create(nil);
if bStart then inherited Create(False) // создать задачу и сразу запустить
else inherited Create(True); // создать приостановленную задачу
end;
procedure Thread2.Execute;
begin
dTimer.OnTimer:=OnTimerClose;
dTimer.Interval:=3000;
dTimer.Enabled:=true;
while not Terminated do
begin
sleep(1000);
end;
end;
procedure Thread2.OnTimerClose(Sender: TObject); // обработка таймера выполнения события
begin
showmessage('Thread 2');
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
thread:=Thread1.Create(true);
end;
end.
Reindeer Moss Eater (2005-09-15 12:13:00) [15]Мало потоков.
Таймеры начинают устойчиво работать где-то после десятого потока.
Digitman (2005-09-15 12:09:00) [16]у тебя ошибка в программе