Текущий архив: 2005.10.09;
Скачать: CL | DM;
Вниз
В потоке не вызывается событие ttimer (запутался в потоках) Найти похожие ветки
← →
msgipss (2005-09-15 12:06) [0]Здравствуйте знатоки, помогите пожалуйста понять ситуацию,
Есть тестовая форма, на ней кнопка, по кнопке создаю, запускаю Thread, в этом Thread"е создаю запускаю еще 1 Thread, в последнем треде есть ttimer, так вот событие этого таймера не могу получить, не срабоатывает оно, в первом пробовал - срабатывает без проблем.
← →
Digitman © (2005-09-15 12:09) [1]у тебя ошибка в программе
← →
Reindeer Moss Eater © (2005-09-15 12:13) [2]Мало потоков.
Таймеры начинают устойчиво работать где-то после десятого потока.
← →
msgipss (2005-09-15 12:51) [3]разрешите вам показать пример кода, 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.
← →
Smithson (2005-09-15 13:32) [4]А зачем в потоке таймер? Объясни плиз.
← →
Digitman © (2005-09-15 13:44) [5]constructor Thread2.Create(bStart:Boolean); // Пишем свой конструктор Create
begin
..
dTimer:= TTimer.Create(nil); //этот таймер создан в контексте доп.потока 1, который никак не обрабатывает сообщения окну созданного в нем таймера
..
end;
← →
msgipss (2005-09-15 13:59) [6]Smithson: А зачем в потоке таймер? Объясни плиз.
иногда нужно менять логику потока через опр.врем.интервал,
согласен можно и без таймера..
Digitman ©: этот таймер создан в контексте доп.потока 1, который никак не обрабатывает сообщения окну созданного в нем таймера
а как запустить таймер в контексте самого потока, если первый поток создает несколько десятков вторых ?
← →
msgipss (2005-09-15 14:15) [7]запустить то можно вот с обработкой будут проблемы, или обрабатывать через основной - да ?,
буду убирать таймеры - считать время ручками
← →
Reindeer Moss Eater © (2005-09-15 14:21) [8]Что делает поток когда ждет тики таймера?
Ничего не делает.
Отсюда вывод, что пока таймер не натикал нужное кол-во времени - поток не нужен вообще.
← →
Digitman © (2005-09-15 14:24) [9]
> как запустить таймер в контексте самого потока
создать и запустить объект-таймер в теле метода Execute() того самого потока, который заинтересован в событиях этого таймера.
> с обработкой будут проблемы
любые проблемы решаемы.
> или обрабатывать через основной - да ?
нет.
основной ответственен ТОЛЬКО за обработку событий тех таймеров. который созданы в его контексте
в общем же случае тот поток, который создал объект-таймер, является ответственным за ожидание и обработку событий этого таймера ... никто за него это не сделает
← →
msgipss (2005-09-15 14:44) [10]Reindeer Moss Eater: Что делает поток когда ждет тики таймера?
не совсем так, пока таймер не натикал исполняется другая логика..
Digitman © а тогда не скромный вопрос - как можно обработать событие, например на выше указанном тесте?
← →
Reindeer Moss Eater © (2005-09-15 14:57) [11]>не совсем так, пока таймер не натикал исполняется другая логика..
Если что-то выполняется, пока таймер не тикает, то значит можно выполнить и что-то еще и другое пока таймер не тикает.
Отсюда вывод - таймер не нужен.
← →
Digitman © (2005-09-15 15:07) [12]
> 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;
← →
Digitman © (2005-09-15 15:09) [13]вру ..
while not Terminated do
begin
if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
DispatchMessage(Msg);
sleep(1);
end;
← →
msgipss (2005-09-16 06:12) [14]Digitman, спасибо - сел в отладку с книжкой 8)
← →
Defunct © (2005-09-16 06:30) [15]господа..вчастности 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 07:41) [16]Defunct:
я ttimer не использую, время считаю сам (можно и так как у Вас),
ttimer попробовал - не получилось, стало любопытно - начал задавать глупые вопросы, ответы получил (спасибо участникам ветки) закрепил теорией - теперь довольный 8)
Страницы: 1 вся ветка
Текущий архив: 2005.10.09;
Скачать: CL | DM;
Память: 0.5 MB
Время: 0.012 c