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

时间:2012-08-09 09:37:27

标签: c++ destructor

我有一个具有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的析构函数吗?因此,如果线程正在执行for-loop中的ThreadFunction,则Stop方法将在a被销毁后调用。当ThreadFunction在被破坏的实例上调用TestFunction时,这可能会导致访问冲突。

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

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

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

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

2 个答案:

答案 0 :(得分:1)

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 〜A

当它不使用虚拟时,结果是: 一个 乙 做一点事 〜A

答案 1 :(得分:1)

正如Rolle和R. Martinho Fernandes所说,我需要将这两个问题分开。

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

所以解决方案是从另一个类(启动线程的同一个类)中停止线程,这个线程负责线程的生命周期。