如何确保对象只有一个线程

How to ensure object has only one thread

我有以下代码:

class Service {
public:
    void start(); // creates thread which creates window and goes to message loop
    void stop();  // sends WM_CLOSE message to thread window
private:
    HANDLE hMutex;
    HANDLE hThread;
    HWND   hWindow;
};

我希望我的 class 执行如下行为:

Service obj;
obj.start(); // new thread
obj.start(); // do nothing because thread already exists

现在我被互斥体覆盖哪个句柄的问题困住了:

void Service::start() {
    // check if service is already running
    if (/*!!*/) // what should I check: (hThread != NULL)? or (hWindow != NULL)?
        return; // no need to create another thread
    else
        hThread = CreateThread(...);
}

您可以简单地检查 hThread 是否是一个有效的句柄:

if (hThread != NULL)
    return;
else
    hThread = CreateThread(...);

CreateThread returns 如果线程成功创建,则为有效句柄,因此请确保在调用 CreateThread 后进行正确处理。您还需要确保在构造函数中将 hThread 初始化为 NULL

Service::Service() : hMutex(NULL), hThread(NULL) etc...
{
}

如果您使用的是 std::thread instead, you could simply check whether the thread was joinable:

class Service
{
public:
    void start();
private:
    std::thread thread;
};
Service::start()
{
    if (thread.joinable())
        return;
}

你可以控制线程句柄的状态hThread,如果它发出信号则意味着线程被终止:

DWORD result = WaitForSingleObject( hThread, 0);

if (result == WAIT_OBJECT_0) {
    // the signal is sent and therefore the thread has been terminated
}
else {
    // the signal is not sent and hThread is alive
}

注意第二个参数是超时时间,非阻塞调用需要设置为0。

你可以查看详细的reference

我会采用 RAII 方式,在构造函数中创建线程并在析构函数中关闭它。主要优点是您不会忘记关闭服务(即使出现异常),并且构造函数一次只能被一个线程调用一次。