Delphi 无窗体DLL使用定时器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Delphi 无窗体DLL使用定时器相关的知识,希望对你有一定的参考价值。

这是CSDN上的一段使用线程无窗体DLL 使用定时器的代码,求完善代码,使程序能运行到//add my code处 。小弟才学,不懂线程,还有在这段代码里面怎么设置定时器时间。没分了,帮帮忙。
原代码链接:http://bbs.csdn.net/topics/290009194

type

TMyThread = class(TThread)

private

FTimer:TTimer;

procedure TimerProc(Sender: TObject);

protected

procedure Execute;override;

public

constructor Create;override;

procedure KillIt;//结束

end;

implementation

procedure TMyThread.TimerProc(Sender: TObject);

begin
//add my code

end;

procedure TMyThread.KillIt;

begin

PostMessage(Handle,WM_QUIT,0,0);

end;

procedure TMyThread.Execute;

begin

FTimer:=TTimer.Create(nil);

try

try

FTimer.Enabled:=false;//需要用的时候Enabled设置为True即可。

FTimer.OnTimer:=TimerProc;

while GetMessage(MsgRec, 0, 0, 0) do begin

TranslateMessage(MsgRec);

DispatchMessage(MsgRec)

end;

Terminate;

finally

FSocket.Free;

end;

finally

FTimer.Free;

end;

end;

如果你需要在DLL中使用定时器。其实也不必创建窗口。只需要调用Windows API接口,具体的方法与步骤如下:

    首先声明一个回调函数。以及一个定时器ID的常整数。

    使用API函数SetTimer来启动这个定时器。

    在不需要定时器时,使用API函数KillTimer来停止这个定时器。

实际用法如下,需要引用Windows单元:

//定时器的ID
const
  TimerID1 = 100;
//定时器的回调函数

procedure TimerProc(hwnd: HWND; uMsg: UINT; idEvent: UINT_PTR; dwTime: DWORD); stdcall;
begin
  //执行你需要的代码
  if (idEvent = TimerID1 )
      Beep;
end;

//在需要创建Timer的时候使用,其中的1000就是定时器的回调周期为1秒
SetTimer(0,TimerID1,1000,@TimerProc);

//在不需要使用定时器的时候停止定时器
KillTimer(0,TimerID1);

当然,如果你对时间的要求比较准确的话,也可以使用Windows多媒体定时器。精确度可以达到1ms左右。具体的使用方法,你可以搜索Delphi 多媒体定时器。

追问

我不需要回调,如果VB使用我的DLL ,回调会使VB非常不稳定,经常崩溃,我只需要再DLL独立使用一个定时器,使用Socket去定时发送一个数据。

追答

我看了一下你的代码,主要是在线程中利用消息循环和TTimer来实现定时器。但是,你需要引用ExtCtrls。而这个单元可能间接地引用了Forms单元。这可能才是你程序不稳定的原因。至于你说使用回调函数会让VB不稳定,其实TTimer也使用到了回调函数。

如果你要坚持用你原来的方法来使用定时器的话,我可以给你例子(需要引用Classes单元):

  TMyThread = class(TThread)
  private
    FTimer: HWND;
    procedure TimerProc(var Message: TMessage);
  protected
    procedure Execute; override;
  public
    procedure KillIt; // 结束
  end;
  
  procedure TMyThread.TimerProc(var Message: TMessage);
begin
  // add my code
  if Message.Msg = WM_TIMER then
  begin
    //执行你需要的代码
    Beep;
  end;
end;

procedure TMyThread.KillIt;
begin
  PostThreadMessage(ThreadID, WM_QUIT, 0, 0);
end;

procedure TMyThread.Execute;
var
  Msg: TMsg;
begin
  try
    //创建一个新的窗口
    FTimer := AllocateHWnd(TimerProc);
    //设置定时器,1000代表定时器的时间为1秒
    SetTimer(FTimer,0,1000,nil);
    //原定的消息循环
    while GetMessage(Msg, 0, 0, 0) do
    begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
    //清理定时器,并释放窗口
    KillTimer(FTimer,0); DeallocateHWnd(FTimer);

    Terminate;
  finally
    FSocket.Free;
  end;
end;

参考技术A 线程技术,在 DOS 时代是有意义的,在 Windows 时代已经毫无意义。你写 Timer.OnTimer 事件就可以,它本身就是独立的线程。如果要防止阻塞,那么在你不确定或者不放心的地方加上一行 Application.ProcessMessages 就好。至于有没有窗口,那只是用户的视觉体验,因为窗口有 Visible 属性。追问

我的DLL封装了使用Socket和PLC通讯的程序,我的DLL没有窗体,如果要在我的无窗体DLL里开定时器,我上网查了一下,应该要写到线程里,但是线程我不熟悉。这里我需要开定时器是由于我需要在DLL里定时发送一个数据给PLC,防止PLC掉线。

追答

Delphi 有线程 Demo ,打开看看,不要窗口就是了。

以上是关于Delphi 无窗体DLL使用定时器的主要内容,如果未能解决你的问题,请参考以下文章

Delphi的DLL里如何实现定时器功能?

delphi 窗体移动事件

系统对话框(如浏览目录)被隐藏到主窗体后面造成程序无法操作的临时处理方式

delphi7制作带窗体的DLL

调用DLL窗体-Delphi实例

Delphi生成即调用带窗体的Dll