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

Вниз

потоки и таймер   Найти похожие ветки 

 
AKMTT   (2006-01-08 23:07) [0]

Доброго времени суток. Мне нужно сделать следующее: после запуска программы проходит некоторое время, к примеру 1 секунда, выполняется некторое действие. Делаю так:

type
 TGameRead=class(TThread)
protected
 procedure Execute;override;
 procedure Tic;
end;
procedure TGameRead.execute;
begin
 repeat
 synchronize(Tic);
 until Terminated
end;procedure TGameRead.Tic;
begin
.....
 Beep;
end;

...
T1:=TGameRead.Create(false);
T1.Priority:=tpLowest;

Код взят из одной статьи.
Но 1ых, он работает не сразу после запуска, а через некоторый промежуток времени, и как проследить что прошла 1а секунда?
Проще говоря мне нужно заменить обычный таймер, чем-нибудь другим, не используя VCL


 
VirEx ©   (2006-01-08 23:14) [1]

{

Имя файла: HRTimer.PAS V1.00
Создан: Апр 17 1997, 06:40, автор John Mertus
Обновлен #6: Окт 12 1997, 10:56 John Mertus

Оболочка для таймера высокой точности при создании приложений под
Win95/WinNT

Var
HRT : THRTimer

HRT := THRTimer.Create;
HRT.StartTimer;  Сброс таймера в ноль
HRT.ReadTimer;   Возвращает отсчитанное время в миллисекундах
начиная со времени старта

HRT.Free;

Список изменений
Версия  1.00 - Первый выпуск
}

{-----------------Модуль HRTimer-------------------John Mertus Апрель 97---}

Unit HRTimer;

{-------------------Объявления-------------------------------}

interface

Uses Windows;

Type

THRTimer = Class(TObject)
Constructor Create;
Function StartTimer : Boolean;
Function ReadTimer : Double;

private
StartTime : Double;
ClockRate : Double;

public
Exists    : Boolean;

End;

{--------------------------Реализация-----------------------------------}

implementation

{------------------Create-------------------------John Mertus----Мар 97-}

Constructor THRTimer.Create;

{ Получаем точное системное время и сохраняем его для дальнейшего       }
{ использования.                                                        }
{                                                                       }
{***********************************************************************}
Var

QW : TLargeInteger;

BEGIN

Inherited Create;
Exists := QueryPerformanceFrequency(QW);
ClockRate := QW.QuadPart;
END;

{------------------StartTimer---------------------John Mertus----Мар 97-}

Function THRTimer.StartTimer : Boolean;

{ Получаем точное системное время и сохраняем его для дальнейшего       }
{ использования.                                                        }
{                                                                       }
{***********************************************************************}
Var

QW : TLargeInteger;

BEGIN

Result := QueryPerformanceCounter(QW);
StartTime := QW.QuadPart;
END;

{-------------------ReadTimer---------------------John Mertus----Мар 97---}

Function THRTimer.ReadTimer : Double;

{ Получаем точное системное время и сохраняем его для дальнейшего       }
{ использования.                                                        }
{                                                                       }
{***********************************************************************}
Var

ET : TLargeInteger;

BEGIN

QueryPerformanceCounter(ET);
Result := 1000.0*(ET.QuadPart - StartTime)/ClockRate;
END;

end.


 
AKMTT   (2006-01-08 23:19) [2]


 ClockRate := QW.QuadPart;

Вот в этой строчке возникает ошибка:Record, object or class type required


 
EvS   (2006-01-08 23:27) [3]

http://www.cracklab.ru/pro/delphi/Winapifa.php#00086D


 
AKMTT   (2006-01-08 23:30) [4]

Ладно, всем спасибо, на GetTickCount остановился, ничего лучшего не нашел :(


 
Piter ©   (2006-01-08 23:41) [5]

Я честно говоря не понял.

Автору нужно отсчитать сколько прошло времени? Тогда GetTickCount.

Или нужно сделать свой таймер средствами WinApi? Тогда вот:

Вопрос: как создать таймер средствами Win32Api

Ответ: нужно воспользоваться функцией SetTimer, описанной в Windows.pas следующим образом:

function SetTimer(hWnd: HWND; nIDEvent, uElapse: UINT;
 lpTimerFunc: TFNTimerProc): UINT; stdcall;


hWnd - указатель на окно, куда будут посылаться сообщения WM_TIMER при очередной итерации таймера
nIDEvent - задает идентификатор таймера, не должен быть ноль. Игнорируется системой, если hWnd равно нулю
uElapse - время в миллисекундах между итерациями таймера
lpTimerFunc - указатель на процедеру TimepProc, которая должна являться callback функцией и которая будет вызываться системой при каждой итерации таймера

Видно, что существую два пути задания таймера - или задать окно hWnd, куда будут посылаться сообщения WM_TIMER каждые uElapse миллисекунд, или задать указатель на процедуру lpTimerFunc, которая будет вызываться системой каждые uElapse миллисекунд.

1) Рассмотрим первый вариант:

procedure TForm1.Button1Click(Sender: TObject);
begin
 if SetTimer(Handle, 1, 1000, nil)=0 then
   ShowMessage("Не удалось создать таймер!");
end;


При успешном создании таймера, функция SetTimer вернет индентификатор таймера, который мы сами и задали - 1.
Если таймер создать не удалось - функция вернет ноль.
Если таймер создан, то экземпляру TForm1 каждые 1000 миллисекунд (1 секунду) будет посылаться сообщение WM_TIMER. Естественно, нужно это сообщение обрабатывать. У TForm1 объявить метод:

TForm1 = class(TForm)
...
 procedure WMTImer(var Msg: TMessage); message WM_TIMER;
...


И реализовать:

procedure TForm1.WMTImer(var Msg: TMessage);
begin
 beep;
end;


Каждую секунду будем издавать звуковой сигнал.

Чтобы удалить таймер, нужно вызвать функцию KillTimer, передав ей Handle окна и идентификатор таймера (которые указывали при создании таймера) .

KillTimer(Handle, 1);

Стоит заметить, что если в очереди потока стоит хотя бы одно необработанное сообщение от таймера - то новое сообщение от таймера в очередь помещаться не будет. Мicrosoft, наверное, это сделал специально, чтобы исключить забиение очереди необработанными сообщениями какого-то не в меру шустрого таймера по отношению к обработчикам остальных сообщений

2) теперь рассмотрим второй варинт, на основе процедуры TimerProc. Вызов будет такой:

idTimer := SetTimer(0, 0, 1000, @TimerProc);
if idTimer=0 then
 ShowMessage("Не удалось создать таймер!");


В качестве указателя на окно пишем ноль, во второй параметр пишем что хотим (все равно игнорируется), третий - время итераций, четвертый - указатель на процедуру TimerProc, которая будет вызываться системой каждые 1000 миллисекунд. Где-то должна быть объявлена и реализована эта процедура TimerProc (получается, что это callback процедура, значит соглашение о вызове должно быть stdcall, не забывайте):

procedure TimerProc(wnd: HWND; Msg: UINT; idEvent: UINT; Time: DWORD); stdcall;
begin
 beep;
end;


Где wnd - указатель на окно, которое передали функции SetTimer (в нашем случае ноль); Msg - номер сообщения (оно будет равно WM_TIMER); idEvent - идентификатор таймера (тоже значение, которое вернет SetTimer и которое записано в idTimer); Time - время в миллисекундах, которое прошло с момента загрузки Windows на момент генерации этого события таймера (данное значение эквивалентно тому, что возвращает функция GetTickCount).

Делает этот код тоже самое, что и первый пример - издает сигнал каждую секунду. При этом никакие передаваемые аргументы я не анализирую. Хотя, например, можно создать два таймера и назначить им одинаковую TimerProc. А различать вызовы от одного и другого таймеров по значению idEvent.

Значение, возвращаемое функцией SetTimer сохраняется в какую-нибудь переменную idTimer: UINT. Это нужно, чтобы потом можно было удалить таймер, так как во втором примере id таймера назначется системой.

Стоит отметить, что функция TimerProc вызывается системой в контексте того потока, который вызвал функцию SetTimer для установки таймера. Причем вызов TimerProc происходит неявно при вызове приложением функции DispatchMessage, поэтому если приложение не делает выборки и диспетчеризации сообщений - то вызова SetTimer не будет.

Чтобы удалить таймер, надо просто вызвать функию KillTimer, передав ей Handle окна (который указывали при создании таймера) и идентификатор таймера (которое вернула система).

KillTimer(0, idTimer);

3) Есть еще и третий вариант - не указывать ни handle окна, ни процедуру TimerProc:

idTimer := SetTimer(0, 0, 1000, nil);

Тогда система просто будет посылать сообщение WM_Timer в очередь потока, который вызвал SetTimer.
В главном потоке отловить такое сообщение можно назначив обработку Application.OnMessage:

...
Application.OnMessage := OnAppMessage;
...

procedure TForm1.OnAppMessage(var Msg: TMsg; var Handled: Boolean);
begin
if Msg.message = WM_TIMER then
 begin
   beep;
   Handled := True;
 end;
end;


При этом какой бы цикл выборки сообщений в потоке не был - нельзя допускать вызова DispatchMessage, так как ведь у этого сообщения Handle=0, а значит оно не будет диспетчеризировано. Поэтому до Application.OnMessage это сообщение "доходит", а вот до Application.DefaultHandler не дойдет.

Файл проекта с данными примерами можно загрузить ЗДЕСЬ

Отвечали: Piter, Ihor Osov"yak


 
begin...end ©   (2006-01-09 09:26) [6]

CreateWaitableTimer



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

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

Наверх




Память: 0.5 MB
Время: 0.025 c
15-1137409586
Ega23
2006-01-16 14:06
2006.02.05
Полный улёт!!! Любителям авиации - к прочтению обязательно!


4-1132995988
VolanD666
2005-11-26 12:06
2006.02.05
Списко процессов


2-1137771999
Baraka
2006-01-20 18:46
2006.02.05
Псевдонимы


2-1137548533
Gena
2006-01-18 04:42
2006.02.05
Delphi7


3-1133868377
Tor
2005-12-06 14:26
2006.02.05
error loading MIDAS.DLL