Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.09.25;
Скачать: CL | DM;

Вниз

TThread + TTimer   Найти похожие ветки 

 
vecna ©   (2005-08-30 16:47) [0]

Че-та мне снова пора в отпуск...
Можно ли успользовать в потоках TTimer? С одной стороны он реализуется APIфункциями, с другой он наследник TComponent и это вызывает сомнения.


 
Erik1 ©   (2005-08-30 17:03) [1]

Нет, поскольку используется механизм сообщений. Для этого надо использовать спецальный таймер. http://www.delphikingdom.com/asp/viewitem.asp?catalogid=434


 
Суслик ©   (2005-08-30 17:10) [2]

Можно, если обрабатывать сообщения самому.

Типа такого (за точность и правильность не ручаюсь, но работает)

type
  TMyThread = class(TThread)
     procedure Execute(); override;
     procedure fOnTimer(Sender: TObject);
     procedure fDoSomething();
  end;

procedure TMyThread.Execute();
var
  kTimer: TTimer;
  kMsg: TMsg;
begin
  kTimer := TTimer.Create(nil);
  try
     kTimer.OnTimer := fOnTimer;
     kTimer.Interval := 1000;
     kTimer.Enabled := True;
     while true do
        if GetMessage(kMsg, 0, 0, 0) then
        begin
           TranslateMessage(kMsg);
           DispatchMessage(kMsg);
        end;
  finally
     kTimer.Free();
  end;
end;

procedure TMyThread.fOnTimer(Sender: TObject);
begin
  Synchronize(fDoSomething);
end;

procedure TMyThread.fDoSomething();
begin
  Form1.Memo1.Lines.Add("a");
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  TMyThread.Create(False);
end;


 
Reindeer Moss Eater ©   (2005-08-30 17:14) [3]

И что же будет делать поток, ожидая очередного тика таймера?
Крутить тупой пустой цикл?

Зачем тогда вообще таймер, если тупой цикл крутится и без него?
:)


 
Суслик ©   (2005-08-30 17:15) [4]


>  [3] Reindeer Moss Eater ©   (30.08.05 17:14)

согласен :)
но на вопрос мой пост вроде отвечает


 
Lamer@fools.ua ©   (2005-08-30 17:15) [5]

Я бы
while true do
заменил на
while not Terminated do


 
Суслик ©   (2005-08-30 17:16) [6]


>  [5] Lamer@fools.ua ©   (30.08.05 17:15)

да это тест, я его за 1.5 минуты написал с отладкой: true - короче


 
vecna ©   (2005-08-30 17:19) [7]

2Суслик
Ага, спасибо, попробую

2Reindeer Moss Eater
Нужно уметь парктически сразу определять, что Terminated = true.


 
Суслик ©   (2005-08-30 17:19) [8]

А зачем в потоке может понадобиться таймер вообще?


 
Reindeer Moss Eater ©   (2005-08-30 17:25) [9]

Вот именно.
Таймер-то зачем?


 
Digitman ©   (2005-08-30 17:43) [10]


> Нужно уметь парктически сразу определять, что Terminated
> = true


и что этому мешает ?
и как этому может помочь таймер, если код обработки его "тика" будет выполнен не иначе как в том же трэде, который у тебя в момент "тика" занят какими-то иными длительнымы вычислениями ?

нет, ну проктологическое решение, конечно же найдется, но надо ли оно ? смею предположить, что ты его просто "не потянешь" за отсутствием достаточных знаний о контексте трэда ..


 
Leonid Troyanovsky ©   (2005-08-31 08:57) [11]


> Reindeer Moss Eater ©   (30.08.05 17:14) [3]
> И что же будет делать поток, ожидая очередного тика таймера?
> Крутить тупой пустой цикл?


Ждать сообщений - GetMessage.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2005-08-31 09:13) [12]


> Суслик ©   (30.08.05 17:10) [2]
..
>   kTimer := TTimer.Create(nil);
..
>      while true do
>         if GetMessage(kMsg, 0, 0, 0) then
>         begin
>            TranslateMessage(kMsg);
>            DispatchMessage(kMsg);


Про true уже говорили, т.е., лучше while GetMessage do.
Кроме того, для такого потока лучше сделать свой Terminate,
который пошлет потоку WM_QUIT. Ну, и, наверное, свой
Free, т.к. Terminate - статический.
Стоит также отметить, что сам TTimer создает окно верхнего
уровня, что такому потоку никчему.
Т.е., можно просто


procedure TimerFunc(hwnd:HWND; msg: UINT; idEvent:UINT; dwTime: DWord); stdcall;
begin
 ..
end;

var
 msg: TMsg;

begin
 SetTimer(0, 0, 1000, @TimerFunc);
 while GetMessage(msg, 0, 0, 0) do
   DispatchMessage(msg);
end.


--
Regards, LVT.


 
Reindeer Moss Eater ©   (2005-08-31 09:22) [13]

>Ждать сообщений - GetMessage.
Круто. А без таймера ему конечно ждать скучно будет.


 
Leonid Troyanovsky ©   (2005-08-31 09:36) [14]


> Reindeer Moss Eater ©   (31.08.05 09:22) [13]
> >Ждать сообщений - GetMessage.
> Круто. А без таймера ему конечно ждать скучно будет.


Я ответил, что он будет делать, ожидая сообщения таймера.
Просто ждать. Скучно ему будет или нет, мне пофиг.

--
Regards, LVT.


 
Reindeer Moss Eater ©   (2005-08-31 09:48) [15]

Вопрос бы в том, что будет делать поток, ожидая тика.
Что бы ждать тика поток должен крутить цикл, в котором конечно он может еще и ждать сообщений и обрабатывать их.
То есть в любом случае необходим цикл.
Отсюда и вытекает второй вопрос: а таймер-то зачем здесь приплетать?


 
Leonid Troyanovsky ©   (2005-08-31 10:12) [16]


> Reindeer Moss Eater ©   (31.08.05 09:48) [15]
> Вопрос бы в том, что будет делать поток, ожидая тика.
> Что бы ждать тика поток должен крутить цикл, в котором конечно
> он может еще и ждать сообщений и обрабатывать их.
> То есть в любом случае необходим цикл.


RTFM: GetMessage.
А лучше почитать Рихтера, про потоки и их очереди.
И про то, что такое спящие потоки.


> Отсюда и вытекает второй вопрос: а таймер-то зачем здесь
> приплетать?


Этот вопрос, видимо, не ко мне.

--
Regards, LVT.


 
Reindeer Moss Eater ©   (2005-08-31 10:55) [17]

В любом случае в потоке будет цикл, либо поток будет использовать функцию ожидания (опять же в цикле)
Поэтому таймер там - не нужен вовсе.


 
Alexander Panov ©   (2005-08-31 10:57) [18]

Для реализации периодического выполнения функции в потоке масса вариантов.
Лучше, хуже - дело вкуса, способностей и знаний.


 
Alexander Panov ©   (2005-08-31 11:00) [19]

Reindeer Moss Eater ©   (31.08.05 10:55) [17]
Поэтому таймер там - не нужен вовсе.


ну почему же - SetTimer - нормальный вариант.


 
Игорь Шевченко ©   (2005-08-31 11:09) [20]

Я бы WaitableTimer использовал или TimerQueue, ни с какими окнами не связано.

По поводу того, зачем нужен таймер в потоке - периодически что-то опрашивать, например, не нагружая основной поток. Аська, например, опрашивает что-то периодически, не мешая набирать сообщение...


 
Digitman ©   (2005-08-31 11:18) [21]


> Alexander Panov


"ключевой" момент всей этой затеи (цитирую автора):


> vecna ©   (30.08.05 17:19) [7]
> Нужно уметь парктически сразу определять, что Terminated
> = true.


Автор, очевидно, наивно предполагает, что таймер - это такая волшебная штука, которая "тикнув" в нужный момент времени немедленно и безусловно "прервет" исполнение трэда (чем бы он, трэд, ни был в этот момент занят) и при этом можно будет проконтролировать состояния флага Terminated, дабы тут же должным образом отреагировать на него.

Если так (а скорей всего так оно и есть), то таймер тут как корове седло: поставленной автором задачи он НЕ решает и решить НЕ может в принципе, ибо "парктически сразу" - понятие весьма растяжимое.


 
Digitman ©   (2005-08-31 11:31) [22]


> Игорь Шевченко ©   (31.08.05 11:09) [20]


пока трэд работает в user time, толку от таймера, сам понимаешь, нет никакого - для обнаружения и обработки "тика" таймера трэд как правило должен переключиться в kernel time .. для немедленной реакции на "тик" это переключение требуется выполнять насколько это возможно чаще, при этом "полезная деятельность" трэда сводится к нулю, ибо "окон" в user time становится все меньше и меньше ... и нужен ли в конечном итоге такой трэд, который только и делает, что чуть ли не без конца (от "рождения" до "смерти") беспокоится только о том, не сработал ли таймер - это нужно осознать прежде всего автору сабжа ..


 
Суслик ©   (2005-08-31 11:36) [23]


>  [12] Leonid Troyanovsky ©   (31.08.05 09:13)
> Про true уже говорили, т.е., лучше while GetMessage do.


ну это типа "быстрый" пример, не претендующих на законченность.


> Кроме того, для такого потока лучше сделать свой Terminate,
> который пошлет потоку WM_QUIT.


Это я понимаю зачем - иначе не прервется ожидание getmessage и все "зависнет".


> Ну, и, наверное, свой
> Free, т.к. Terminate - статический.


А вот этого не понимаю? Это про что?

-----------
За поправки про окно спасибо, интересно было почитать.


 
Игорь Шевченко ©   (2005-08-31 11:51) [24]

Digitman ©   (31.08.05 11:31) [22]


> для обнаружения и обработки "тика" таймера трэд как правило
> должен переключиться в kernel time


Вах! Зачем переключаться ? в SetWaitableTimer указываешь, какую процедуру надо вызывать при достижении нужного интервала, например.

hint: вызовы для получения и обработки сообщений тоже в режиме ядра выполняются, так что профит несущественный :)


 
Digitman ©   (2005-08-31 11:58) [25]


> Игорь Шевченко ©   (31.08.05 11:51) [24]


Все бы было расчудесно, Игорь, если бы не ма-а-аленькая "загвозка":

If you call SetWaitableTimer and the thread is not in an alertable state, the completion routine is canceled

так что, один черт, придется как можно чаще переводить трэд в тревожное состояние, хотя бы на мизерные промежутки времени ..

шило на мыло, ч.н.)


 
Игорь Шевченко ©   (2005-08-31 12:08) [26]

Digitman ©   (31.08.05 11:58) [25]

Не совсем шило на мыло. Тебе не надо делать окон, обрабатывать у них WM_TIMER и т.п.

А что касается ожидания, то это вполне естественно. В этой концепции предполагается, что поток не будет активно заниматься какой-то другой активной деятельностью помимо работы с таймером.


 
Digitman ©   (2005-08-31 12:38) [27]


> Игорь Шевченко ©   (31.08.05 12:08) [26]


> Не совсем шило на мыло. Тебе не надо делать окон, обрабатывать
> у них WM_TIMER и т.п


Об окнах и речи не идет ...
А ожидание WM_TIMER при SetTimer() точно так же как и ожидание колбэка при SetWaitableTimer() требует kernel time, так что никаких явных преимуществ задействования того или иного таймера в таком абстрактном изложении автором задачи я не вижу


> В этой концепции предполагается, что поток не будет активно
> заниматься какой-то другой активной деятельностью помимо
> работы с таймером


В том-то и дело, что эта концепция вроде бы противоречит авторскому видению решения ...
Ему ведь нужно что ? Ему, как пока видно из его постов, нужно следующее : запустить какой-то там таймер (который будет отсчитывать некие предельно малые интервалы времени) и спокойно продолжать делать в трэде свои "дела", не задумываясь ни о каких "режимах ядра", "тревожных состояниях", "ожиданиях" и прочей непонятной и потому якобы несущественной лабуде ..
Мол, когда таймер тикнет, то выполнение некоего основного алгоритма трэда само по себе (!) прервется и при этом будет вызвана некая п/программа, где первым делом будет осуществляться проверка флага Terminated на предмет не закруглиться ли немедленно этому трэду "по хозяйству"..


 
Leonid Troyanovsky ©   (2005-08-31 12:48) [28]


> Суслик ©   (31.08.05 11:36) [23]

> > Ну, и, наверное, свой
> > Free, т.к. Terminate - статический.

> А вот этого не понимаю? Это про что?


В реализации Destroy можно увидеть Terminate, однако,
т.к. Terminate не виртуальный, то вызван будет он,
а не новая его реализация.

Т.е., если кто-то привык к тому, что Free остановит поток,
то должен озаботится и своим деструктором,
который вызовет нужный Terminate.

--
Regards, LVT.


 
Суслик ©   (2005-08-31 12:51) [29]


>  [28] Leonid Troyanovsky ©   (31.08.05 12:48)

тогда не "свой free", а "свой destroy". Так?
Тогда понял.


 
Leonid Troyanovsky ©   (2005-08-31 13:05) [30]


> Суслик ©   (31.08.05 12:51) [29]

> тогда не "свой free", а "свой destroy". Так?


Конечно.
Хорошо, что хоть деструкторы виртуальны :)

--
Regards, LVT.


 
Игорь Шевченко ©   (2005-08-31 13:48) [31]

Digitman ©   (31.08.05 12:38) [27]


> Об окнах и речи не идет ...


Согласен, об окнах речь не идет. Но о цикле выборки сообщений, в любом случае, речь идет. Которая выборка сообщений тоже обращается к ядру.


> так что никаких явных преимуществ задействования того или
> иного таймера в таком абстрактном изложении автором задачи
> я не вижу


Автор задачу изложил на совсем уж высоком уровне абстрации, я из его объяснения задачи не понял вообще.
Я вижу то преимущество, что не надо организовывать выборку сообщений.


 
Digitman ©   (2005-08-31 14:19) [32]


> Игорь Шевченко ©   (31.08.05 13:48) [31]


ну ладно, что там бестолку рассуждать ...

"вот предет барин - барин нас рассудит")



Страницы: 1 вся ветка

Текущий архив: 2005.09.25;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.025 c
1-1125627631
SergProger
2005-09-02 06:20
2005.09.25
Сообщения Windows


1-1125894450
record
2005-09-05 08:27
2005.09.25
ctrl+a --- ctrl+c в Memo


14-1125083646
Gero
2005-08-26 23:14
2005.09.25
Junction на сетевую папку


2-1124204973
Андрей Молчанов
2005-08-16 19:09
2005.09.25
невидимые TTreeNode


2-1124305845
Привет
2005-08-17 23:10
2005.09.25
Динамическое создание кнопок