Текущий архив: 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.54 MB
Время: 0.036 c