Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
6-67423
alx99
2003-02-28 03:03
2003.04.21
как сделать простейший веб браузер?


1-67373
CussedJohn
2003-04-10 11:24
2003.04.21
Чтение Нового Формата Файла 16-бит. INTEGER


1-67267
$Hic0
2003-04-11 12:19
2003.04.21
byte2bin


1-67299
_MAX_
2003-04-11 17:33
2003.04.21
Закрывание ToolBar


8-67394
ГС ТОФ
2003-01-21 13:34
2003.04.21
Печать растровых изображений





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский