tsm*_*smr 4 delphi multithreading vcl
我正在开发一个多线程应用程序(RAD Studio XE5).在应用程序的开始,我创建一个单独的线程,只要主表单生效.
我能够将消息从线程发送到我的应用程序中创建的任何表单,但是我找不到相反的方法,从主VCL线程向工作线程发送消息.
在创建主窗体时,我创建了工作线程并将句柄复制到公共变量中:
serverThread := TMyThread.Create(True, ServerPort + 1);
serverThreadHandle := serverThread.Handle; // SAVE HANDLE
serverThread.Start;
Run Code Online (Sandbox Code Playgroud)
然后(从另一种形式FrmSender)我向线程发送一条消息:
PostMessage(uMain.serverThreadHandle, UM_LOC_VCLMSG, UM_LOC_VCLMSG, Integer(PStrListVar));
Run Code Online (Sandbox Code Playgroud)
这是线程的执行过程:
procedure TMyThread.Execute;
var
(..)
vclMSG : TMsg;
str1, str2 : string;
(..)
begin
while not(Terminated) do
begin
Sleep(10);
if Assigned(FrmSender) then
if FrmSender.HandleAllocated then
if PeekMessage(vclMSG, FrmSender.Handle, 0, 0, PM_NOREMOVE) then
begin
if vclMSG.message = UM_LOC_VCLMSG then
begin
try
pStrListVar := pStrList(vclMSG.lParam);
str1 := pStrListVar^.Strings[0];
str2 := pStrListVar^.Strings[1];
finally
Dispose(pStrListVar);
end;
end;
end;
(.. do other stuff ..)
end;
end;
Run Code Online (Sandbox Code Playgroud)
但是,PeekMessage()永远不会返回true,就好像它从未接收任何消息一样.我已经尝试将参数更改为PeekMessage():
PeekMessage(vclMSG, 0, 0, 0, PM_NOREMOVE);
Run Code Online (Sandbox Code Playgroud)
但没有结果.有任何想法吗?
PeekMessage(vclMSG, FrmSender.Handle, 0, 0, PM_NOREMOVE)
Run Code Online (Sandbox Code Playgroud)
第二个参数意味着您只会检索发送给发件人的邮件FrmSender.Handle.但是你把邮件发送给收件人了uMain.serverThreadHandle.这是为什么PeekMessage永远不能回归的原因之一.
像你一样从线程访问VCL是错误的.表单的句柄受VCL窗口重新创建的影响,并且有一个明确的比赛HandleAllocated和Handle.因此,即使您需要知道FrmSender.Handle,在线程中询问它也是错误的.
您实际上是将消息发送到线程句柄而不是窗口句柄.这意味着消息永远不会被发送,另一个原因是PeekMessage无法返回.如果你在打电话时检查了返回值,PostMessage你就会知道这一点.
我会使用其中一个PostThreadMessage,或者通过调用将消息发布到线程中分配的窗口AllocateHWnd.
一旦您设法实际发送消息,您的使用PM_NOREMOVE意味着消息队列永远不会被清空.
你Sleep对我的使用看起来非常可疑.为什么不使用GetMessage并阻止消息到达.无论何时你看到一个电话Sleep,都要非常怀疑.
您的强制转换Integer将导致64位构建中的指针截断.要转换的正确类型是LPARAM.
我希望还有其他错误,这些只是我在快速2分钟扫描中看到的错误.
在与创建指定窗口的线程关联的消息队列中放置(发布)消息,并返回而不等待线程处理消息.
要在与线程关联的消息队列中发布消息,请使用PostThreadMessage函数.
因此,你应该使用PostThreadMessage:
将消息发布到指定线程的消息队列.它返回而不等待线程处理消息.
请特别注意备注部分.收件人线程需要一个消息队列.按照以下步骤强制线程有一个:
WaitForSingleObject在调用之前,使用该函数等待事件设置为信号状态PostThreadMessage.在将消息发布到的线程中,PeekMessage如此处所示调用以强制系统创建消息队列.
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE)
Run Code Online (Sandbox Code Playgroud)设置事件,以指示线程已准备好接收已发布的消息.
然后,在使用时PeekMessage,将句柄值传递-1给函数,如文档所示.
| 归档时间: |
|
| 查看次数: |
664 次 |
| 最近记录: |