如何从没有创建该窗口的线程更新窗口?

时间:2016-01-15 18:34:27

标签: c++ multithreading user-interface winapi

我想创建一个能够更新GUI元素的线程,而主线程(创建GUI)运行一些长时间的计算,我不知道如何做到这一点。我在MSVC ++中使用win32 API。

因为这些计算很长并且是RAM密集型的,所以我想避免弄乱它们并将它们放在一个线程中。这意味着我希望能够直接从线程处理此GUI更新,而主窗口不必处理任何WndProc消息。

在最简单的情况下,我只是希望能够从线程内部更新单个静态控件,但最终我希望能够在主窗口上绘制或更新其中的位图图像作为数据从外部设备滚入。我并不意味着线程可以完全接管窗口过程。

我尝试过非常简单的方法,例如:

// Global
HWND display;
DWORD WINAPI myThread(LPVOID threadParameter);

int APIENTRY WinMain(_In_ HINSTANCE hInstance,
                 _In_opt_ HINSTANCE hPrevInstance,
                 _In_ LPWSTR    lpCmdLine,
                 _In_ int       nCmdShow){

    // Blah Blah Create main Window and display object, which is a "STATIC" Blah Blah

    HANDLE myThreadHandle = CreateThread(0, 0, myThread, (LPVOID)display, 0, &myThreadID);
    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32PROJECT7));

    MSG msg;

    // Main message loop:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    CloseHandle(myThreadHandle);
    return (int) msg.wParam;
}
// other function outside WinMain(){
DWORD WINAPI myThread(LPVOID threadParameter) {
    // I've passed in my static handle here.
    HWND hwnd = (HWND)threadParameter;
    // My hope was that this would update the text of the static window, but...
    PostMessage(hwnd, WM_SETTEXT, 0, (LPARAM)"10");
    // After this message the static window still hasn't updated with the text "10".
    return 0;
};

但这不起作用(静态控制只是不更新​​),这只是一个猜测,所以我可能做了一些愚蠢的事情。我无法在C ++中找到有关正确程序的任何资源,但我正在寻找this MSDN resource(在C#中)的内容。

我当然可以上传我的尝试的全部代码,如果这很有用,但我认为我可能在错误的轨道上,所以我只是包含了这个片段。

2 个答案:

答案 0 :(得分:1)

您不能让UI线程完成工作,并从工作线程更新UI。系统根本不起作用。主线程需要保持响应并及时处理其消息队列。需要从UI线程执行与Windows的交互。

您只需要撤销工作分配。让UI线程在UI上工作,让工作线程进行密集的工作。

您似乎担心密集型工作需要花费时间并使用内存,并且某些线程不适合该任务。但事实并非如此。线程可用于执行长时间运行的计算。线程可以使用内存。

似乎你已经让自己陷入了困境。处理UI线程上的UI,并在工作线程上完成工作。这就是它的全部内容。

答案 1 :(得分:0)

您需要将指针传递给HWND display

CreateThread()中使用

HANDLE myThreadHandle = CreateThread(0, 0, myThread, (LPVOID)&display, 0, &myThreadID);

在你的主题中使用:

HWND hwnd = (HWND)(*threadParameter);
  

我想创建一个能够更新GUI元素的线程   而主线程(创建GUI)运行一段时间   计算

如评论中所述,工作应该在工作线程中完成,让主线程处理绘图,鼠标,键盘等。重绘窗口是只有当主线程没有忙于做其他事情时才会这样做,比如计算等。

就个人而言,我更喜欢使用用户消息,并将它们发布到父窗口(而不是直接将WM_SETTEXT发布到子窗口),让父窗口处理其余部分。