C ++在Windows API中创建一个单独的线程,程序终止了吗?

时间:2016-10-06 21:21:29

标签: c++ windows multithreading winapi

由于某些原因使用线程并将其分离,尝试在单独的线程中运行窗口的消息循环,程序才会终止?

如果你向下看CFrame构造函数,我做了一个线程t1传入startMessageLoop函数然后分离线程,以便while循环不会支配整个程序,而是程序只是终止?这甚至发生在入口点是int main()的地方,你必须使用系统(" PAUSE")来阻止程序终止。

#define UNICODE

#include <windows.h>
#include <thread>

const wchar_t CLASS_NAME[] = L"Window Class";
static int nWindows = 0; // Number of ongoing windows 

class Size { // Size of the window
  private:
    int width;
    int height;
  public:
     Size() {}
     Size(int width, int height) :width(width), height(height) {}
  int getWidth() {
     return width;
  }
  int getHeight() {
     return height;
  }
};

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
    case WM_DESTROY: nWindows--; break;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}  

void RegisterDetails(HINSTANCE hInstance) { // Registers WNDCLASS
    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;
    RegisterClass(&wc);
}

void startMessageLoop() { // This is the message loop which must be in a   separate thread
    MSG msg;
    while (nWindows) { 
        GetMessage(&msg, NULL, 0, 0);
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

HWND CreateAWindow(LPCWSTR title, Size size, HINSTANCE hInstance) {
    if (nWindows == 0) { // The WNDCLASS only needs to be registered once
        RegisterDetails(hInstance);
    }
    HWND hwnd = CreateWindowEx(0, CLASS_NAME, title, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, size.getWidth(), size.getHeight(), NULL, NULL, hInstance, NULL);
    ShowWindow(hwnd, 5);
    return hwnd;
}


class CFrame {

private:
    HINSTANCE hInstance;
    Size size;
    HWND hwnd;

public:
    CFrame() { 
}

CFrame(LPCWSTR title, Size size, HINSTANCE hInstance) :size(size), hInstance(hInstance) 
    { 
        hwnd = CreateAWindow(title, size, hInstance);
        nWindows++;
        if (nWindows == 1) {
            std::thread t1(startMessageLoop);
            t1.detach();
        }
    }
};

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PWSTR pCmdLine, int nCmdShow) {

    CFrame frame1 = CFrame{ L"Window1", Size{ 800, 600 }, hInstance };

}

2 个答案:

答案 0 :(得分:2)

Windows消息队列与线程绑定。发布到窗口的消息将转到与该窗口关联的线程的消息队列。如果在一个线程上创建一个窗口,那就是其消息队列将为该窗口获取消息的线程,并且是需要消息循环将消息分派给窗口的Windows过程的线程。

您的main创建了一个窗口,并且还启动了一个在第二个线程的消息队列上运行消息循环的新线程。由于没有任何东西放在第二个消息队列中,你的第二个线程永远不会做任何事情。

然而,你的主人会立即退出。这将终止您的主线程以及整个程序。

答案 1 :(得分:2)

您的进程退出是因为您的主线程(wWinMain)退出,其他线程在这方面不予考虑。你应该让wWinMain等到其他线程运行,例如通过调用t1.join(因为它是CFrame构造函数中的局部变量,你必须传递对它的引用)。

您的代码的另一个问题是连接到全局变量nWindows的Race Condition,您应该使用CriticalSection或Mutex保护它,或使用InterlockedIncrease / Decrease。 (但这不是你的程序立即退出的原因。)

你必须从startMessageLoop调用CreateAWindow,以便在线程t1上从Windows接收消息。

我希望这是某种实验/学习项目,因为不推荐使用更多的UI线程(它不会通过减少延迟来使程序更具响应性,并且不会像处理边界那样强制执行模块化)。