Multithreading GetMessage中的wparam值不是我所期望的(Delphi XE4)
我正在开发一个DelphiXe4服务应用程序。该服务为一些长时间运行的任务启动线程,线程通过PostThreadMessage调用返回状态 主ServiceExecute循环如下所示:Multithreading GetMessage中的wparam值不是我所期望的(Delphi XE4),multithreading,delphi,delphi-xe4,getmessage,Multithreading,Delphi,Delphi Xe4,Getmessage,我正在开发一个DelphiXe4服务应用程序。该服务为一些长时间运行的任务启动线程,线程通过PostThreadMessage调用返回状态 主ServiceExecute循环如下所示: procedure TScanService.ServiceExecute(Sender: TService); var CurrentMessage: TMsg; begin LogServerEvent('ServiceExecute', 'Starting'); while not Termin
procedure TScanService.ServiceExecute(Sender: TService);
var
CurrentMessage: TMsg;
begin
LogServerEvent('ServiceExecute', 'Starting');
while not Terminated do
begin
if not PeekMessage(CurrentMessage, 0, WM_NULL, msgHigh, PM_NOREMOVE) then
begin
Sleep(1000);
Continue;
end;
GetMessage(CurrentMessage, 0, WM_NULL, msgHigh);
LogServerEvent('ServiceExecute', 'CurrentMessage.message', IntToStr(CurrentMessage.message));
LogServerEvent('ServiceExecute', 'CurrentMessage.wParam', IntToStr(CurrentMessage.wParam));
LogServerEvent('ServiceExecute', 'CurrentMessage.lParam', IntToStr(CurrentMessage.lParam));
gThreadNumber: Integer;
LogThreadEvent('Execute', 'Found Notice, Thread number: ' + IntToStr(gThreadNumber));
PostThreadMessage(ParentThreadID, msgFound, gThreadNumber, 6);
在线程中,消息发送如下所示:
procedure TScanService.ServiceExecute(Sender: TService);
var
CurrentMessage: TMsg;
begin
LogServerEvent('ServiceExecute', 'Starting');
while not Terminated do
begin
if not PeekMessage(CurrentMessage, 0, WM_NULL, msgHigh, PM_NOREMOVE) then
begin
Sleep(1000);
Continue;
end;
GetMessage(CurrentMessage, 0, WM_NULL, msgHigh);
LogServerEvent('ServiceExecute', 'CurrentMessage.message', IntToStr(CurrentMessage.message));
LogServerEvent('ServiceExecute', 'CurrentMessage.wParam', IntToStr(CurrentMessage.wParam));
LogServerEvent('ServiceExecute', 'CurrentMessage.lParam', IntToStr(CurrentMessage.lParam));
gThreadNumber: Integer;
LogThreadEvent('Execute', 'Found Notice, Thread number: ' + IntToStr(gThreadNumber));
PostThreadMessage(ParentThreadID, msgFound, gThreadNumber, 6);
消息到达良好,消息编号正确(msgFound=WM_USER+1);但是,我为wParam和lParam发送了0,6,收到的是4,0。我错过了什么
注意:该代码只有2个线程在运行,其中一个是使用不同消息编号的计时器,并且在发生这种情况时不会发送任何内容。在
t服务
代码中,您可以找到以下代码:
const
CM_SERVICE_CONTROL_CODE = WM_USER + 1;
....
procedure TService.Controller(CtrlCode: DWord);
begin
PostThreadMessage(ServiceThread.ThreadID, CM_SERVICE_CONTROL_CODE, CtrlCode, 0);
if ServiceThread.Suspended then ServiceThread.Resume;
end;
因此,t服务
正在发送与您的邮件编号相同的邮件。你怎么能把他们分开?嗯,你不能
来自WM用户的文档
:
用于定义私有窗口类使用的私有消息,通常采用WM_USER+x的形式,其中x是一个整数值
通常,这将用于发送到窗口的消息,消息的含义是特定于类的。当我阅读TService
代码时,设计者认为他们完全控制消息队列,有权确定其私有消息的含义。这样做的最终结果是,您不能在WM_USER
范围内使用线程消息,因为它们已被TService
类保留
您的主要选择:
- 将您的消息发送到窗口李>
- 使用
确保消息id的唯一性李>RegisterWindowMessage
- 停止使用windows消息(并非专门用于服务)并使用其他机制进行通信李>
HWND
。。。RTL使用WM_USER+x
范围内的一些消息;如果没有更多的代码,很难说,但也有可能是您接收到了散乱的消息。如果将-1
用于PeekMessage
和GetMessage
的HWND
参数,您将限制仅拾取使用NULL
HWND发布的消息(否则也会获取窗口消息)-前者只包括使用带有空句柄的PostMessage
发送的消息,以及使用posthreadmessage
@J.发送的消息。我错过了。我通常使用PostThreadMessage在线程和GUI之间进行通信,并在收到消息时始终检查Msg.hwnd=0
;我没有想过从服务中这样做。CM_服务控制代码是WM_USER+1,wparam as 4是服务控制查询。TService.Controller可能正在发布它。如果是这样的话,检查hwnd将没有帮助。如果我们遵守文档,也没有好处。“仅当多个应用程序…”时使用RegisterWindowMessage。我认为WM_USER+没有任何真正的危险,当您使用“PostThreadMessage”时,它永远不会被发送到窗口。那么它的意思就是你想要它的意思。WM_APP+可能会更好。@Sertac ok,如果用户检查hwnd,则不会出现混淆。然而,我认为WM_用户是用于窗口类的。如果是我,我会创建一个窗口,永远不会调用PostThreadMessage。-1“这意味着您不能将此范围内的消息与PostThreadMessage一起使用”-消息ID的WM\u用户
范围与PostThreadMessage()
(如果没有,TService
本身不会运行,因为它使用PostThreadMessage)(WM_USER+1)
在内部将SCM请求发布到t服务
消息队列)。对PostThreadMessage()的消息ID没有限制
接受。它所关心的只是一个附加了消息队列的有效线程ID。其他参数按原样发布到该线程的消息队列中。OP只需选择一个已被TService
使用的消息ID,并将其消息发布到TService
发布其权限的同一线程消息队列中将消息发送给。仅此而已。这是使用WM_USER
的真正危险,而不是它根本不能与PostThreadMessage()
一起使用。好的,我能够确认我收到的消息不是来自我的线程,因此作为临时解决方案,我将消息编号移到了更高的位置。