Форум: "Основная";
Текущий архив: 2003.04.21;
Скачать: [xml.tar.bz2];
Вниз
Консольное приложение и timer Найти похожие ветки
← →
Вася (2003-04-10 10:29) [0]У кого какие предложения. Как в консольном приложении, построенном по правилам процедурного программирования, использовать системный timer. Ведь в таком случае придется создавать окно, пусть даже невидимое, вставлять обработку очереди, неужели нет варианта попроще?
← →
Digitman (2003-04-10 10:33) [1]
> в таком случае придется создавать окно, пусть даже невидимое,
> вставлять обработку очереди
не обязательно.
альтернатива - использование Waitable Timer"а
см. Create/SetWaitableTimer и ф-ции ожидания
← →
Вася (2003-04-10 10:35) [2]Сеачас гляну.
← →
NAlexey (2003-04-10 10:47) [3]Не надо создавать окна, упоси боже. Достаточно SetTimer, KillTimer.
← →
Digitman (2003-04-10 10:54) [4]
> NAlexey
> Не надо создавать окна, упоси боже
И куда же, по-твоему, таймер будет посылать WM_TIMER, если первый параметр (wWnd) требует хэндл целевого окна ?
← →
Digitman (2003-04-10 11:00) [5]пардон.
можно и без окна, конечно, если указать TimerProc() и организовать как положено цикл ожидания и диспетчеризации сообщений потоку, создавшему таймер
← →
Вася (2003-04-10 11:11) [6]Что-то я не понял. А куда же денется обращение к окну?
VOID CALLBACK TimerProc(
HWND hwnd, // handle of window for timer messages
UINT uMsg, // WM_TIMER message
UINT idEvent, // timer identifier
DWORD dwTime // current system time
);
← →
evvcom (2003-04-10 11:25) [7]По-моему в качестве hWnd в TimerProc передается hWnd из SetTimer, а в SetTimer написано:
hWnd - Identifies the window to be associated with the timer. This window must be owned by the calling thread. If this parameter is NULL, no window is associated with the timer and the nIDEvent parameter is ignored
т.е. можно обойтись и без окна и hWnd=0, а в TimerProc можно и не обрабатывать этот hWnd.
← →
Вася (2003-04-10 11:29) [8]Чтож нужно пробовать.
← →
Digitman (2003-04-10 11:35) [9]When you specify a TimerProc callback function, the DispatchMessage function simply calls the callback function instead of the window procedure. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER.
← →
Fiend (2003-04-10 11:44) [10]Да создайте окно и не долбите себе мозги.
Или сделайте как Дигитмэн говорит.
Уже вот два варьянта есть, что еще нужно
← →
Zelius (2003-04-10 11:49) [11]Можно по другому: создаешь TEvent и вызываешь его WaitFor(Timeout), а потом анализируешь результат.
← →
Вася (2003-04-10 12:32) [12]Все вроде правильно создаю очередь, описываю CallBack для SetTimer`а, но куда воткнуть эту очередь? И где правильнее создать Timer, до вызова главной процедуры внутри ее или еще где.
begin
Main;
end.
А в Main`е пошли поочередно вызываться процедуры и функции.
← →
evvcom (2003-04-10 12:37) [13]Очередь? Значит выбор пал на создание окна (пусть даже скрытого). Тогда посмотри как сделан TTimer в Дельфи. Кода там немного, разберешься быстро.
← →
Вася (2003-04-10 12:59) [14]Окно я даже и не пытался создавать, и не буду, очередь может работать самостоятельно.
← →
Digitman (2003-04-10 13:07) [15]
//класс "безоконного" таймер-трэда
tathread = class(tthread)
protected
procedure MsgTimer(var Message: TWMTimer); message WM_TIMER; // не будем выпендриваться с собственными структурами - воспользуемся подходящей готовой - TWMTimer
procedure Execute; override;
end;
procedure tathread.Execute;
var
msg: tmsg;
idTimer: THandle;
begin
PeekMessage(msg, 0, 0, 0, PM_NOREMOVE);
FreeOnTerminate := True;
idTimer := SetTimer(0, 0, 3000, Pointer(1)); // 3 сек.
try
while not terminated and GetMessage(msg, 0, 0, 0) do
begin
if msg.hwnd = 0 then
Dispatch(Msg.Message)
else
DispatchMessage(msg);
end;
finally
killtimer(0, Message.TimerID);
end;
end;
// обработчик события таймера
procedure tathread.MsgTimer(var Message: TWMTimer);
begin
Terminated := True; // терминируем код.поток
messagebox(0, PChar("TimerId = " + inttostr(Message.TimerID) + ", current systemtime (in ticks) = " + inttostr(Message.Result)), "Timer Event Message", mb_ok);
end;
...
tathread.Create(false); // старт код.потока, инициирующего таймер
// через время ~ 3 сек однократно появится диалоговое окно, открываемое callback-ф-цией таймера
← →
Вася (2003-04-10 13:25) [16]А куда ссылается Pointer(1) при создании таймера? И куда все-таки влепить
procedure tathread.Execute
в моем процедурном проекте?
← →
NAlexey (2003-04-10 13:30) [17]О чем спор, я не пойму, так не будет работать?
const
Interval = 500;
var
NumTimer: Cardinal;
procedure OnTimer;
begin
(* ... *)
end;
procedure BlahBlah;
begin
NumTimer := SetTimer(0, 1, Interval, @OnTimer);
end;
procedure KullBlahBlah;
begin
KillTimer(0, NumTimer);
end;
← →
Digitman (2003-04-10 13:33) [18]
> А куда ссылается Pointer(1) при создании таймера
А никуда не ссылается ! Фиктивный параметр, лишь бы не nil
> И куда все-таки влепить procedure tathread.Execute в моем
> процедурном проекте?
"влеплять" его никуда не нужно, это только пример организации "безоконного" таймера в доп.кодовом потоке, организуемом на базе стандартного TThread
и, кстати, ничто не мешает в "процедурном проекте" использовать ООП-приемы/логику на базе VCL
← →
Zelius (2003-04-10 13:40) [19]var Event: TEvent;
procedure tathread.Execute;
begin
while not terminated do
begin
DoThreadWork;
if Event.WaitFor(5000) <> wrTimeout then Terminate;
end;
end;
← →
NAlexey (2003-04-10 13:40) [20]>Вася
Ну так как? Будет так работать или нет?
← →
Вася (2003-04-10 14:02) [21]>NAlexey
>Ну так как? Будет так работать или нет?
естесственно нет так ты используешь OnTimer (кусок ООП), а в моей программе применение ООП категорически недопустимо. Больше всего мне нравится вариант Digitman`а.
← →
NAlexey (2003-04-10 14:09) [22]А так?
const
Interval = 500;
var
NumTimer: Cardinal;
procedure OnSuperTimer;
begin
(* ... *)
end;
procedure BlahBlah;
begin
NumTimer := SetTimer(0, 1, Interval, @OnSuperTimer);
end;
procedure KullBlahBlah;
begin
KillTimer(0, NumTimer);
end;
← →
Digitman (2003-04-10 14:14) [23]
> Вася
Где ты там, в примере от <NAlexey> ООП-приемы увидел ?)
Это как раз не он, а я рекомендовал тебе внедрить ради такого случаая ООП-фрагмент с использованием VCL)
← →
panov (2003-04-10 14:37) [24]Вот еще пример:
program ConsTimer;
{$APPTYPE CONSOLE}
uses
SysUtils,classes,syncobjs,windows;
type
TMTimer = class(TThread)
private
_interval: Cardinal;
_proc: procedure(aStr: ShortString);
_Counter: Cardinal;
public
constructor Create(aProc: Pointer;aInterval:Cardinal);
procedure Execute;override;
procedure Display;
end;
var
MT: TMTimer;
cs: TCriticalSection;
procedure Disp(aStr:ShortString);
begin
WriteLn("Test:"+aStr);
end;
procedure TMTimer.Display;
begin
if Assigned(_proc) then
begin
_proc(IntToStr(_Counter));
end;
end;
constructor TMTimer.Create(aProc: Pointer;aInterval:Cardinal);
begin
inherited Create(True);
FreeOnTerminate := True;
_interval := aInterval;
@_proc := aProc;
_Counter := 0;
Priority := tpTimeCritical;
Resume;
end;
procedure TMTimer.Execute;
begin
while not Terminated do
begin
Sleep(_interval);
Inc(_Counter);
if _Counter>100 then Terminate;
cs.Enter;
Display;
cs.Leave;
end;
Self.ReturnValue := _Counter;
end;
begin
cs := TCriticalSection.Create;
try
MT := TMTimer.Create(@Disp,50);
MT.WaitFor;
finally
cs.Free;
end;
end.
← →
Вася (2003-04-11 05:21) [25]>Где ты там, в примере от <NAlexey> ООП-приемы увидел ?)
Виноват, каюсь, совсем слепой был.
>NAlexey © (10.04.03 14:09)
скорее всего немного не так.
const
Interval = 500;
var
NumTimer: Cardinal;
procedure OnSuperTimer;
begin
(* ... *)
if ... then
KillTimer(0, NumTimer);
end;
procedure BlahBlah;
begin
NumTimer := SetTimer(0, 1, Interval, @OnSuperTimer);
end;
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.04.21;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.008 c