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

Posted

技术标签:

【中文标题】C++ 在 Windows API 中创建一个单独的线程,程序终止?【英文标题】:C++ making a separate thread in the Windows API, program terminates? 【发布时间】:2016-10-06 21:21:28 【问题描述】:

由于某种原因,使用线程并分离它试图在程序刚刚终止的单独线程中运行窗口的消息循环?

如果你低头看CFrame的构造函数,我做了一个线程t1,传入startMessageLoop函数,然后分离线程,这样while循环就不会支配整个程序,而是程序只是终止?这甚至发生在入口点是 int main() 时,您必须使用 system("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 ;


【问题讨论】:

您似乎在重复同一个问题。你想在这里做什么?您是否意识到您可以拥有一个进程、一个线程以及多个窗口和拥有的窗口?不建议创建多个 GUI 线程。 您是否尝试过将您的nWindows 变量设为atomic&lt;int&gt;?即使你从主线程将它设置为1,其他线程也可能不会读取相同的值。 WINAPI - I would like to have the message pump ongoing in a separate thread的可能重复 “这样 while 循环不会支配整个程序” - 重复的问题有一个 answer 已经解释过,这个假设是错误的。并提供可行的替代方案。 【参考方案1】:

Windows 消息队列绑定到线程。发布到窗口的消息进入与该窗口关联的线程的消息队列。如果您在一个线程上创建一个窗口,则该线程的消息队列将为该窗口获取消息,并且该线程需要一个消息循环来将消息分派到窗口的 windows 过程。

您的 main 创建一个窗口并启动一个新线程,该线程在第二个线程的消息队列上运行一个消息循环。由于第二个消息队列中没有放入任何内容,因此您的第二个线程永远不会做任何事情。

但是,您的 main 会立即退出。这会终止您的主线程以及您的整个程序。

【讨论】:

【参考方案2】:

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

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

您必须从 startMessageLoop 调用 CreateAWindow 才能在线程 t1 上接收来自 Windows 的消息。

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

【讨论】:

以上是关于C++ 在 Windows API 中创建一个单独的线程,程序终止?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 QML 中访问 C++ 类对象,而不是在 QML 中创建单独的对象?

如何在 Windows ( C++ ) 中创建进程以运行另一段代码?

在 C++ 中创建 Windows 共享库时如何实现接口隔离

如何在 c++ 中创建一个适用于 Windows 和 linux 的文件夹(目录)[重复]

指针对象在 Visual C++ 6.0 中创建 windows 错误

在 Windows 中创建 C++ 非阻塞计时器