gpt4 book ai didi

multithreading - PostMessage 在线程中返回 "invalid window handle"

转载 作者:行者123 更新时间:2023-12-03 15:00:41 25 4
gpt4 key购买 nike

背景:我正在使用 OmniThreadLibrary 在后台加载批处理模式 ADO 存储过程。我在打开 SP 后交换连接,做了一些稍微狡猾的事情,但这似乎相当可靠。我正在使用 PostMessage 将消息发送回调用表单,这在我的测试应用程序中有效。 Primoz 的通信 channel 适合我,我将它们用于线程间通信,但对于我们的主应用程序,我试图通过使用标准 PostMessage 调用来避免这种依赖性,就像我们在应用程序中其他地方所做的那样。

问题:不幸的是,当我将其放入我们的主应用程序中时,线程中的 PostMessage 调用开始失败,并显示 1400:无效的窗口句柄。

我已经随意添加了额外的 PostMessage 调用和日志代码来尝试找到问题,但我现在没有想法了。代码是样板:

const WM_PW_ADLQUEUEEMPTY = WM_USER + 11;
...
if PostMessage (OwnerHandle, WM_PW_ADLPROGRESS, QueueID, 10) then
pwDebugLog ('TADLQueue.Run WM_PW_ADLPROGRESS send to ' + IntToHex (OwnerHandle, 8) + ' (IsWindow '+BoolToStr(IsWindow(OwnerHandle),true)+') OK for Queue ' + IntToStr (QueueID))
else
pwDebugLog ('TADLQueue.Run WM_PW_ADLPROGRESS send to ' + IntToHex (OwnerHandle, 8) + ' (IsWindow '+BoolToStr(IsWindow(OwnerHandle),true)+') failed for Queue ' + IntToStr (QueueID));

但是一系列调用的日志对我来说并不是很有启发。请注意,时间后面的四个十六进制数字是来自 GetCurrentThreadID 的线程 ID。

15:41:53.221 1614  TpwAsyncDataLoader.RunQueue WM_PW_ADLPROGRESS send to  00A5110C (IsWindow True)    OK for Queue -6
15:41:53.265 13B4 TADLQueue.Run WM_PW_ADLPROGRESS send to 00A5110C (IsWindow True) OK for Queue -6
15:41:53.554 13B4 TADLQueueManager.WriteSysErrorMessageToDatabase Postmessage 00A5110C (IsWindow False) failed with 1400 Invalid window handle

有人能解释一下吗?我对窗口句柄在查看时如何变得无效感到困惑,但这就是它对我来说的样子。

我能想到的一件事是,我在这里显示的表单不处理消息,并且我看到“消息队列已满”失败,而不是它看起来的 IsWindow(handle) 失败。我该如何测试呢?

最佳答案

在某些情况下,句柄会被重新创建,尤其是当您更改窗口标志时。这可能就是您的应用程序中发生的情况。

到目前为止,我发现有关重新创建 Windows 句柄的所有信息是 this post来自 Allen Bauer,但我确信会阅读 Peter Below 撰写的更详细的文章。不幸的是我似乎找不到那个。

Finally, you need to be aware of cases where your handle may need to get recreated. This can happen if the surrounding form or the parent component's handle goes through a recreate process. Up until more recent releases of Windows, the only way to change some window flags was to destroy the handle and recreate with new flags in the CreateWindowEx() call. There are many components that still do this. You know if you're in a recreate situation by checking (csRecreating in ControlState).

编辑

实际上不是我想到的 Peter 的帖子,但它可能会给你一些新的想法。

The form will not have a handle until you show it the first time (unless something in the form load sequence request the handle) but the handle is not destroyed when you hide the form and unless you do something that forces the form to recreate the handle, e.g. change its border style or border icons, or call RecreateWnd yourself the handle will stay the same.

It may not be desirable but it cannot be avoided, at least not the way Delphi drag&dock is currently implemented. When you dock the dragged form to another form it becomes a control (with WS_CHILD window style) and that means that its window handle has to be destroyed and recreated with the new style. And destroying the window handle of a container control automatically destroys the handles for all child controls as well.

There is also the fact that the forms window handle is destroyed and recreated when you assign to its Parent property. This also destroys and recreates the handles for all controls on the form.

关于multithreading - PostMessage 在线程中返回 "invalid window handle",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3474227/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com