以封锁消息循环处理消息

2023-09-06 16:05:20 作者:執念

我有一个有点问题有两个应用程序之间的交互。

I have a bit of an issue with an interaction between two applications.

您可以复制的问题,code是这样的:

You can replicate the issue with code like this:

using (Form1 frm = new Form1())
{
    frm.ShowDialog();
}

Thread.Sleep(120000);

使用这个code,一个单独的应用程序,这是我们无法控制,冻结当我们的应用程序运行时的code中的 Thread.sleep代码部分。实际上,我们已经发生的事情,虽然已经在此之前错误的接收端上的一个好主意:在其他应用程序有来自本地的回调 EnumWindows的方法,该方法不检查看是否窗户可见使用IsWindowVisible本地方法。它调用然后当 GetWindowText时或可能的其他一些功能,它死了。

Using this code, a separate application, which we do not control, freezes when our application is running the Thread.Sleep portion of the code. We actually have a good idea of what's happening, having been on the receiving end of this bug before: the other app has a callback from the native EnumWindows method which doesn't check to see if windows are visible using the IsWindowVisible native method. Then when it calls GetWindowText or possible some other function, it hangs.

这样做的原因窍门是,它试图说服我们(现已关闭)的窗口,仍然注册了一个手柄,但不发送到它的队列中的消息作出反应,因此调用者只是坐在那里无限期(直到窗口完全我们的Thread.Sleep后死亡)。

The reason for this hang is that it is trying to talk to our (now closed) window, which still has a handle registered, but doesn't respond to messages sent to its queue, and so the caller just sits there indefinitely (until the window fully dies after our Thread.Sleep).

下面是一些示例$ C $下的贱民的应用程序,我们必须处理的:

Here is some sample code for the "untouchable" application that we have to deal with:

public bool RunTest()
{
    return NativeMethods.EnumWindows(new NativeMethods.EnumWindowsProc(EnumWindowsCallback), IntPtr.Zero);
}

private bool EnumWindowsCallback(IntPtr windowHandle, IntPtr parameter)
{
    NativeMethods.SendMessage(windowHandle, 0x000E, IntPtr.Zero, IntPtr.Zero);
    return true;
}

如果您运行的第一个code,关闭它打开的窗口中,然后运行第二个code块在一个单独的进程,第二个(EnumWindows的)进程将挂起。

If you run the first code, close the window that it opens, then run the second code block in a separate process, the second (EnumWindows) process will hang.

我的问题是,我要解决这个问题,而不能只解决了code在挂程序。我可以踢窗户关进一个单独的线程,但似乎笨拙,有点脆弱。有谁知道的方式使用本地通话,或任何其他更直接的方法来清理这个问题呢?

My problem is that I have to deal with this, and can't just fix the code in the hanging application. I can kick the window off into a separate thread, but that seems clumsy and somewhat fragile. Does anyone know of a way to clean this problem up using native calls, or any other more direct method?

推荐答案

而不是调用的睡眠您可以使用一个可等待计时器(与创建 CreateWaitableTimer 函数),并继续运行一个消息循环(使用 MsgWaitForMultipleObjects 函数),直到计时器到期。

Instead of calling Sleep you can use a waitable timer (created with the CreateWaitableTimer function) and continue to run a message loop (using the MsgWaitForMultipleObjects function) until the timer expires.