消息队列上的无限循环

时间:2013-09-24 14:54:39

标签: delphi

我正在使用另一个进程中注入的DLL。在这个DLL中,我创建了一个Thread,其中包括设置2个Timers并执行KeyboardHook(SetWindowsHookEx WH_KEYBOARD_LL)...为了使这个钩子和2个定时器工作,我需要创建一个Message Pump过程。我将这个消息泵称为我的线程中的最后一个东西,正如你在我的Thread.Execute中看到的那样:

procedure MyMainThread.Execute;
begin
  while not Terminated do
    begin
      MyThread:= Self;
      StartKeyboardHook;
      StartUp;
      SetTimer(0, 0, 60000, @MyMainThread.ContactHome);
      SetTimer(0, 0, 40000, @MyMainThread.MapProc);   
      CreateMessagePump;
      Terminate;
    end;
end;

好的,在CreateMessagePump调用之后,我做了一个Terminate,因为我相信Message Pump是一个无限循环,如果我从中退出,会发生错误,所以我需要终止我的Thread。 CreateMessagePump就是这个:

procedure MyMainThread.CreateMessagePump;
var
  AppMsg: TMsg;
begin
  while GetMessage(AppMsg, 0, 0, 0) do
    begin
      TranslateMessage(AppMsg);
      DispatchMessage(AppMsg);
    end;
  //if needed to quit this procedure use PostQuitMessage(0);
end;

我这样做是正确的吗?我的意思是,相信这个循环是无限的是正确的吗?

1 个答案:

答案 0 :(得分:2)

Execute方法中的循环毫无意义。由于循环体的最后一个动作是调用Terminate,因此循环体只能运行一次。写得像这样:

procedure MyMainThread.Execute;
begin
  MyThread:= Self;
  StartKeyboardHook;
  StartUp;
  SetTimer(0, 0, 60000, @MyMainThread.ContactHome);
  SetTimer(0, 0, 40000, @MyMainThread.MapProc);   
  CreateMessagePump;
end;

你的消息循环很好。有些人可能会警告您更密切地检查GetMessage的返回值,但您的使用情况确实很好。请参阅Raymond对此主题的讨论:http://blogs.msdn.com/b/oldnewthing/archive/2013/03/22/10404367.aspx


目前尚不清楚,但似乎有理由认为您作为计时器程序传递的内容与所需的功能签名不兼容。 SetTimer单元中Windows的声明导致不会对您传递的回调执行类型检查。这意味着你可以绝对传递任何东西。编译器迫使您使用@运算符的事实是您遇到问题的警告信号。

出路是停止使用@运算符,并使用SetTimer的固定声明。您应该使用Sertac在之前的一个问题中提供的代码:Using Process32First/Next inside DLL procedure