从析构函数停止线程的正确方法

Proper way to stop a thread from a destructor

本文关键字:方法 线程 析构函数      更新时间:2023-10-16

我有一个类,它有一个Start方法来启动一个以预定义的时间间隔执行虚拟ThreadFunction的线程。Stop 方法设置一个事件并等待线程终止(通过线程句柄上的WaitForSingleObject)。

MyThread 的析构函数中,我调用 Stop 方法。因此,每当我删除实例时,我都会确定线程在删除返回之前已停止。

class MyThread
{
    void Start();
    void Stop();
    ~MyThread() { Stop(); }
    virtual VOID ThreadFunction() { }
};

接下来我有一个派生自MyThread的类:

class A : MyThread
{
    virtual VOID ThreadFunction()
    {
        for (int i = 0; i < 1000; i++)
            TestFunction();
    }
    void TestFunction() { // Do something }
};

请考虑以下代码:

A a = new A();
a->Start();
delete a;

问题是delete a会先调用A的析构函数,然后再调用MyThread的析构函数,对吗?因此,如果线程在ThreadFunction中执行for-loop,则Stop方法将在a被破坏后被调用。当ThreadFunction调用TestFunction已破坏的实例时,这可能会导致访问冲突。

解决方案是向调用 Stop 方法的class A添加一个析构函数,如下所示:

class A : MyThread
{
    ~A()
   {
       Stop();
   }
}

但是因为我有一个更复杂的类层次结构,它涉及多个继承的类,这意味着我必须在每个析构函数中调用 Stop 方法,这将导致只为一个需要删除的实例调用 Stop 方法很多次。

还有其他方法可以解决这个问题吗?

MyThread 中的析构函数应定义为"虚拟"。

class A{
public:
    A(){cout<<"A"<<endl;}
    virtual ~A(){cout<<"~A"<<endl;}
};
class B : public A{ 
public:
    B(){cout<<"B"<<endl;}
    ~B(){cout<<"~B"<<endl;}
};
int main(){
    A* b = new B();
    cout<<"do something"<<endl;
    delete b;
    b = NULL;
    return 0;
}

结果是:一个B做点什么~乙~一个

当它不使用虚拟时,结果是:一个B做点什么~一个

正如Rolle和R. Martinho Fernandes所建议的那样,我需要将这两个问题分开。

class MyThread不应自行启动或停止,因为它的责任应仅限于它执行的代码,而不是线程的生存期。

因此,解决方案是从另一个类(启动线程的同一类)停止线程,该类负责线程的生存期。