Arn*_*old 3 delphi multithreading
为了编写一个MIDI音序器,我需要一个稳定的脉冲,它调用一个时序例程,该例程具有绝对优先于程序中的任何其他内容,并且优先于计算机中的任何内容.我通过使用TimeSetEvent这样做:
TimeSetEvent (FInterval, 0, TimerUpdate, uInt32 (Self), TIME_PERIODIC);
Run Code Online (Sandbox Code Playgroud)
其中TimerUpdate是一个回调函数,它恢复一个优先级为tpTimeCritical的独立线程,并调用一个例程(FOnTimer)来处理所有MIDI事件.
procedure TThreaded_Timer.Execute;
begin
if Assigned (FOnTimer) then
begin
while not Terminated do
begin
FOnTimer (Self);
if not Terminated then Suspend;
end; // while
end; // if
Terminate;
end; // Execute //
Run Code Online (Sandbox Code Playgroud)
虽然这种结构比我之前尝试的一些东西要好得多,但它仍然对某些事件非常敏感.令我惊讶的是,每次显示提示都会出现断断续续的情况.为什么简单的提示会导致时间关键线程中断?当然我可以把它关掉,但哪些令人讨厌的惊喜还在等着我?
使用专为此目的而设计的多媒体计时器.Delphi定时器非常糟糕,只能在空闲时间得到关注.基于线程的计时器仅在该线程受到关注时才有用.MMTimer在内核级别运行,并提供非常重要的回调.我们用它来进行硬件排序自动化控制它是如此的好.
这是我的单位,实现MMTimer作为一个更容易使用的TTimer.使用"重复"使其成为单次或重复.
unit UArtMMTimer;
interface
uses
Classes,
SysUtils,
ExtCtrls,
MMSystem;
type
TArtMMTimer = class( TObject )
constructor Create;
destructor Destroy; override;
PRIVATE
FHandle : MMResult;
FRepeat : boolean;
FIntervalMS : integer;
FOnTimer : TNotifyEvent;
FEnabled : boolean;
procedure RemoveEvent;
procedure InstallEvent;
procedure DoOnCallback;
procedure SetEnabled( AState : boolean );
procedure SetIntervalMS( AValue : integer );
PUBLIC
property Enabled : boolean
read FEnabled
write SetEnabled;
property OnTimer : TNotifyEvent
read FOnTimer
write FOnTimer;
property IntervalMS : integer
read FIntervalMS
write SetIntervalMS;
end;
implementation
uses
Windows;
// TArtMMTimer
// --------------------------------------------------------------------
procedure MMTCallBack(uTimerID, uMessage: UINT;
dwUser, dw1, dw2: DWORD) stdcall;
var
Timer : TArtMMTimer;
begin
Timer := TArtMMTimer( dwUser );
Timer.DoOnCallback;
end;
constructor TArtMMTimer.Create;
begin
Inherited Create;
FIntervalMS := 100;
FRepeat := True;
end;
destructor TArtMMTimer.Destroy;
begin
FOnTimer := nil;
RemoveEvent;
Inherited Destroy;
end;
procedure TArtMMTimer.RemoveEvent;
begin
If FHandle <> 0 then
begin
timeKillEvent( FHandle );
FHandle := 0;
end;
end;
procedure TArtMMTimer.InstallEvent;
var
iFlags : integer;
begin
RemoveEvent;
If FRepeat then
iFlags := TIME_PERIODIC Or TIME_CALLBACK_FUNCTION
else
iFlags := TIME_CALLBACK_FUNCTION;
FHandle := timeSetEvent(
FIntervalMS,
0,
@MMTCallBack,
DWord(Self),
iFlags );
end;
procedure TArtMMTimer.SetEnabled( AState : boolean );
begin
If AState <> FEnabled then
begin
FEnabled := AState;
If FEnabled then
InstallEvent
else
RemoveEvent;
end;
end;
procedure TArtMMTimer.DoOnCallback;
var
NowHRCount, WaitHRCount,IntervalHRCount : THRCount;
begin
If Assigned( FOnTimer ) then
FOnTimer( Self );
end;
procedure TArtMMTimer.SetIntervalMS( AValue : integer );
begin
If AValue <> FIntervalMS then
begin
FIntervalMS := AValue;
If Enabled then
begin
Enabled := False;
Enabled := True;
end;
end;
end;
// End TArtMMTimer
// --------------------------------------------------------------------
end.
Run Code Online (Sandbox Code Playgroud)