Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

В потоке не вызывается событие 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]

у тебя ошибка в программе


Наверх

Титульная страница Поиск, карта сайта Написать письмо