PDA

Просмотр полной версии : Использование TTImer в приложении без окон



delphi-coder
23.03.2004, 21:11
Проблема в следующем: создаю приложение-демон (без окон, сходно с консольным приложением). В нём нужно использовать таймер. Делаю так:

var
job: TTimer;

procedure jobTimer;
begin
{some code here}
end;

begin
job := TTimer.Create(nil);
job.Interval := 1000;
job.OnTimer := jobTimer;
end;

Всё проходит нормально, но когда доходит до job.OnTimer := jobTimer;, получаю сообщение об ошибке от кимпилятора: "[Error] QTSaver.dpr(176): Incompatible types: method pointer and regular procedure". Подскажите как быть. Спасибо.

Eugie
24.03.2004, 19:07
Если у твоего приложение нет message loop, то обычный таймер работать вообще не будет. Дело в том, что TTimer - это просто дельфовая обертка для API-шного таймера, а он предполагает наличие очереди сообщений. Более того, TTimer реализует API-таймер, непосредственно связанный с окном (см.TTimer.Create).

Короче, здесь нужен другой вариант. Может, имеет смысл сделать свой таймер. Не знаю, как там в Линукс, но в Винде я бы использовал QueryPerformanceCounter в отдельном потоке. Опять же, в Винде есть еще несколько таймер-объектов, типа waitable timer (см. CreateWaitableTimer,...) и timer-queue timer (см. CreateTimerQueue,...), но здесь ничем помочь не могу - сам не юзал :)

Naeel Maqsudov
26.03.2004, 08:35
Incompatible types: method pointer and regular procedure"

Это ошибка даже не связанная с наличием или отсутствием окон. Это ошибка на этапе компиляции.
OnTimer имеет тип procedure of object (т.е. МЕТОД) это совсем не то, что указатель на процедуру.




procedure TSomeObject.jobTimer;
begin
{some code here}
end;

...
job.OnTimer := SomeObject1.jobTimer;

//разумеется SomeObject1 должен быть типа TSomeObject и быть инициализирован (Created)



Не могу сейчас поглядеть исходники TTimer, чтобы сказать что-то более определенное, но попробуйте, должно получиться.

ЗЫ.
Обязательно напишите.

delphi-coder
26.03.2004, 13:17
Для Timer.OnTimer получилось назначить нужную процедуру, когда я сделал её методом класса:


type
timerevent = class(TObject)
Public
procedure MTTimer(Sender: TObject);
procedure QRTimer(Sender: TObject);
procedure saverTimer(Sender: TObject);
end;

procedure timerevent.savertimer(Sender: TObject);
begin
lalala
end;

procedure timerevent.MTTimer(Sender: TObject);
lalala

procedure timerevent.QRTimer(Sender: TObject);
lalala

//Main
var
tmev: timerevent;
job, saver: TTimer;

tmev := timerevent.Create;

job := TTimer.Create(nil);
If lowercase(ddesrv) = 'mt' then job.OnTimer := tmev.MTTimer;
If lowercase(ddesrv) = 'qr' then job.OnTimer := tmev.QRTimer;

saver := TTimer.Create(nil);
saver.OnTimer := tmev.saverTimer;

While (True) do
begin
Application.ProcessMessages;
sleep(1000);
end;

Этот код нормально работает, таймеры тоже работают. Но раздражает этот бесконечный цикл While (True) do, да и вызывать Application.ProcessMessages; не хочется - приходится использовать Forms, а это прибавляет размера файлу, да и зачем мне в ресурсах иконки\курсоры\т.д., если у меня даже окна нету?! Можно ли это как-нибудь по-другому реализовать?

Eugie
26.03.2004, 16:35
Incompatible types: method pointer and regular procedure"


Это ошибка даже не связанная с наличием или отсутствием окон. Это ошибка на этапе компиляции.
OnTimer имеет тип procedure of object (т.е. МЕТОД) это совсем не то, что указатель на процедуру.

Совершенно верно, забыл сказать самое главное :) Собственно, весь пафос был посвящен невозможности использовать TTimer в программе без очереди сообщений.

delphi-coder, еще раз обращаю внимание: либо TTimer - и тогда нужно использовать Forms и всю архитектуру, заложенную в TApplication, либо придется искать другие варианты (см.выше)