多线程 – 具有隐藏窗口的线程的线程消息循环?

前端之家收集整理的这篇文章主要介绍了多线程 – 具有隐藏窗口的线程的线程消息循环?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个Delphi 6应用程序,它有一个专用于与使用SendMessage()和WM_COPYDATA消息与外部程序连接的外部应用程序进行通信的线程.因此,我使用AllocateHWND()创建一个隐藏窗口来满足此需求,因为由于SendMessage()函数只接受窗口句柄而不是线程ID,因此线程消息队列将无法工作.我不确定的是在线程Execute()方法中放入什么.

我假设如果我使用GetMessage()循环或创建一个带有WaitFor *()函数的循环调用,那么线程将阻塞,因此线程的WndProc()永远不会处理来自外部程序的SendMessage()消息对?如果是这样,放入Execute()循环的正确代码是什么,它不会不必要地消耗cpu周期,但是一旦收到WM_QUIT消息就会退出?如果有必要,我总是可以使用Sleep()循环,但我想知道是否有更好的方法.

解决方法

AllocateHWnd()(更具体地说,MakeObjectInstance())不是线程安全的,所以你必须小心它.最好直接使用CreatWindow / Ex()(或者像 DSiAllocateHwnd()一样使用AllocateHWnd()的线程安全版本.

在任何情况下,HWND都与创建它的线程上下文绑定,因此您必须在Execute()方法中创建和销毁HWND,而不是在线程的构造函数/析构函数中.此外,即使使用SendMessage()向您发送消息,它们也来自另一个进程,因此在其拥有的线程执行消息检索操作之前,HWND不会处理它们,因此该线程需要自己的消息循环.

您的Execute()方法应如下所示:

  1. procedure TMyThread.Execute;
  2. var
  3. Message: TMsg;
  4. begin
  5. FWnd := ...; // create the HWND and tie it to WndProc()...
  6. try
  7. while not Terminated do
  8. begin
  9. if MsgWaitForMultipleObjects(0,nil^,False,1000,QS_ALLINPUT) = WAIT_OBJECT_0 then
  10. begin
  11. while PeekMessage(Message,PM_REMOVE) do
  12. begin
  13. TranslateMessage(Message);
  14. DispatchMessage(Message);
  15. end;
  16. end;
  17. end;
  18. finally
  19. // destroy FWnd...
  20. end;
  21. end;
  22.  
  23. procedure TMyThread.WndProc(var Message: TMessage);
  24. begin
  25. if Message.Msg = WM_COPYDATA then
  26. begin
  27. ...
  28. Message.Result := ...;
  29. end else
  30. Message.Result := DefWindowProc(FWnd,Message.Msg,Message.WParam,Message.LParam);
  31. end;

或者:

  1. // In Delphi XE2,a virtual TerminatedSet() method was added to TThread,// which is called when TThread.Terminate() is called. In earlier versions,// use a custom method instead...
  2.  
  3. type
  4. TMyThread = class(TThread)
  5. private
  6. procedure Execute; override;
  7. {$IF RTLVersion >= 23}
  8. procedure TerminatedSet; override;
  9. {$IFEND}
  10. public
  11. {$IF RTLVersion < 23}
  12. procedure Terminate; reintroduce;
  13. {$IFEND}
  14. end;
  15.  
  16. procedure TMyThread.Execute;
  17. var
  18. Message: TMsg;
  19. begin
  20. FWnd := ...; // create the HWND and tie it to WndProc()...
  21. try
  22. while not Terminated do
  23. begin
  24. if WaitMessage then
  25. begin
  26. while PeekMessage(Message,PM_REMOVE) do
  27. begin
  28. if Message.Msg = WM_QUIT then Break;
  29. TranslateMessage(Message);
  30. DispatchMessage(Message);
  31. end;
  32. end;
  33. end;
  34. finally
  35. // destroy FWnd...
  36. end;
  37. end;
  38.  
  39. {$IF RTLVersion < 23}
  40. procedure TMyThread.Terminate;
  41. begin
  42. inherited Terminate;
  43. PostThreadMessage(ThreadID,WM_QUIT,0);
  44. end;
  45. {$ELSE}
  46. procedure TMyThread.TerminatedSet;
  47. begin
  48. PostThreadMessage(ThreadID,0);
  49. end;
  50. {$IFEND}

猜你在找的Java相关文章