我有一个具有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方法被多次调用只需要删除一个实例。
还有其他方法可以解决这个问题吗?
答案 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
不应该启动或停止,因为它的责任应该仅限于它执行的代码,而不是线程的生命周期。
所以解决方案是从另一个类(启动线程的同一个类)中停止线程,这个线程负责线程的生命周期。