Atl*_*las 8 delphi winapi multithreading
我的应用程序有几个线程:1)主线程2)2个子主线程(每个都有消息循环,如下所示),由TFQM使用3)n工作线程(简单循环,包含Sleep())
我的问题是,当我关闭我的应用程序时,工作线程设法正常退出,但当我发出WM_QUIT关闭它们时,2个子主线程中的一个挂起(从不退出).
procedure ThreadProcFQM(P: Integer); stdcall;
var
Msg: TMsg;
_FQM: TFQM;
begin
_FQM := Ptr(P);
try
_FQM.fHandle := AllocateHwnd(_FQM.WndProc);
while GetMessage(Msg, 0, 0, 0) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
finally
DeallocateHWnd(_FQM.fHandle);
SetEvent(_FQM.hTerminated);
end;
end;
Run Code Online (Sandbox Code Playgroud)
procedure TFQM.Stop;
begin
PostMessage(fHandle, WM_QUIT, 0, 0);
WaitForSingleObject(hTerminated, INFINITE);
if hThread <> INVALID_HANDLE_VALUE then
begin
CloseHandle(hThread);
hThread := INVALID_HANDLE_VALUE;
end;
end;
Run Code Online (Sandbox Code Playgroud)
gab*_*abr 11
如果我在你的代码中指出几个问题......
1)您没有检查AllocateHwnd的输出.是的,很可能它永远不会失败,但仍然......
2)AllocateHwnd belogs out of try..finally!如果失败,则不应调用DeallocateHwnd.
3)AllocateHwnd不是线程安全的.如果你同时从多个线程调用它,你可能会遇到问题.阅读更多.
正如戴维所说,使用MsgWaitForMultipleObjects而不是创建隐藏的消息窗口.然后使用PostThreadMessage向线程发送消息.
如果我可以在这里插一个完全免费的产品 - 请使用我的OmniThreadLibrary.比直接使用Windows消息传递更简单.
我遇到了同样的问题,我发现我不应该创建一个隐藏的窗口来接收消息.线程已经有一个消息系统.
我认为您正在创建Windows句柄并将其存储在fHandle中,但GetMessage会检查您的线程的消息循环.因此消息PostMessage(fHandle,WM_QUIT,0,0); getmesssage永远不会收到.
您可以使用PostThreadMessage将消息发布到您的线程,并在线程中使用GetMessage(CurrentMessage,0,0,0).唯一重要的区别是你必须通过调用从线程启动消息循环
PeekMessage(CurrentMessage, 0, WM_USER, WM_USER, PM_NOREMOVE);
Run Code Online (Sandbox Code Playgroud)
你应该从这开始,而不是你的设置,而不是开始你的循环.
你应该从peek消息开始的原因是确保在初始化threadprocedure期间发送的消息不会丢失.
奇怪的是,目前我无法找到我所学到的参考资料,但我的猜测是新闻组社区.
小智 7
1)您的线程中不需要AllocateHwnd.第一次调用GetMessage将为该线程创建一个单独的消息队列.但是为了向线程发送消息,你应该使用PostThreadMessage函数.
请注意,在调用PostThreadMessage时,仍无法创建队列.我经常使用建筑:
while not PostThreadMessage(ThreadID, idStartMessage, 0, 0) do
Sleep(1);
Run Code Online (Sandbox Code Playgroud)
确保创建消息队列.
2)为了终止线程循环,我定义了自己的消息:
idExitMessage = WM_USER + 777; // you are free to use your own constant here
Run Code Online (Sandbox Code Playgroud)
3)不需要单独的事件,因为您可以将线程句柄传递给WaitForSingleObject函数.所以,你的代码看起来像:
PostThreadMessage(ThreadID, idExitMessage, 0, 0);
WaitForSingleObject(ThreadHandle, INFINITE);
Run Code Online (Sandbox Code Playgroud)
考虑到ThreadID和ThreadHandle是不同的值.
4)因此,您的ThreadProc将如下所示:
procedure ThreadProcFQM; stdcall;
var
Msg: TMsg;
begin
while GetMessage(Msg, 0, 0, 0)
and (Msg.Message <> idExitMessage) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12595 次 |
| 最近记录: |