【问题标题】:How to correctly destroy window that is running from another thread?如何正确销毁从另一个线程运行的窗口?
【发布时间】:2021-04-04 01:05:51
【问题描述】:

我试图实现的目标是收听有关锁定、解锁等的会话通知。由于架构和避免阻塞主线程,我必须在另一个线程中执行此操作。这是我正在做的事情:


LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_WTSSESSION_CHANGE:
        switch (wParam) {
        case WTS_CONSOLE_CONNECT:
        case WTS_SESSION_LOGON:
        case WTS_REMOTE_CONNECT:
        case WTS_SESSION_UNLOCK:
        case WTS_CONSOLE_DISCONNECT:
        case WTS_REMOTE_DISCONNECT:
        case WTS_SESSION_LOGOFF:
        case WTS_SESSION_LOCK:
        case WTS_SESSION_REMOTE_CONTROL:
        case WTS_SESSION_CREATE:
        case WTS_SESSION_TERMINATE:

            break;
        default:
            break;
        }
        break;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }

    return 0;
}

void startListeningNotifications()
{
    const wchar_t g_szClassName[] = L"myWindowClass";

    WNDCLASSEX wc = {};
    wc.lpfnWndProc = WndProc;
    wc.lpszClassName = g_szClassName;
    wc.cbSize = sizeof(WNDCLASSEX);

    if (!RegisterClassEx(&wc))
    {
        return;
    }

    HWND hwnd = CreateWindowEx(NULL, g_szClassName, L"", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, GetModuleHandle(NULL), NULL);
    if (hwnd == NULL)
    {
        return;
    }

    if (!WTSRegisterSessionNotification(hwnd, NOTIFY_FOR_ALL_SESSIONS))
    {
        return;
    }

    ShowWindow(hwnd, SW_HIDE);

    MSG Msg = {};
    while (GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
}

int main()
{
    std::thread listener(startListeningNotifications);
    listener.join();

    return 0;
}

我现在面临的问题是我不知道如何正确编写 stopListeningNotifications() 方法。我必须以某种方式破坏我的窗口并退出消息循环。请建议如何安全地做到这一点。提前致谢。

【问题讨论】:

  • 您应该知道,每个消息循环都在它自己的线程中运行。因此,简单地向该窗口发送消息并不是一个好主意。我会尝试使用std::condition_variable 来表示它应该关闭的窗口。如果收到通知,接收窗口可以简单地调用它自己的Close() 函数。
  • PostMessageW(hwnd, WM_CLOSE, 0, 0)
  • 但是这个线程安全吗?
  • 当然是线程安全的。这里有什么不安全的地方?

标签: c++ multithreading winapi thread-safety createwindow


【解决方案1】:

提供WndProc函数句柄WM_CLOSEWM_DESTROY

case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
case WM_DESTROY:
        PostQuitMessage(0);
        break;

所以你可以发送WM_CLOSE 消息和线程中创建的窗口的hwnd

PostMessage(hwnd, WM_CLOSE, 0, 0)

【讨论】:

  • 我可以在任何线程中发送此消息吗?在我的情况下,它将是主线程。
  • 您可以向任何线程发送消息,即使是没有创建窗口的线程 (PostThreadMessage),但目标线程必须有消息循环。
  • 我已经尝试过了,但这对我不起作用。但是当我从主线程(没有 PostThreadMessage)尝试这个 PostMessage() 时,它可以工作。
  • PostMessage 与窗口句柄一起使用是线程安全的。
猜你喜欢
  • 2018-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 2012-08-29
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多