Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 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.51 MB
Время: 0.041 c
2-1125649209
kyn66
2005-09-02 12:20
2005.10.09
Как заменить искомый компонент 1 раз?


14-1126873033
Mike B.
2005-09-16 16:17
2005.10.09
На деревню дедушке


2-1125592985
pathfinder
2005-09-01 20:43
2005.10.09
работа с текстовым файлом


3-1125400079
Dragoon
2005-08-30 15:07
2005.10.09
Ошибка table is read only от TQuery


4-1123735019
ndn
2005-08-11 08:36
2005.10.09
Медленная печать на матричном принтере