问候,大家!
我有一个类(比如说,“Switcher”)执行一些非常长的操作并通知其监听器,该操作已完成。操作很长,我将实际切换隔离到单独的线程中:
class Switcher
{
public:
// this is what other users call:
void StartSwitching()
{
// another switch is initiated, I must terminate previous switching operation:
if ( m_Thread != NULL )
{
if ( WaitForThread(m_Thread, 3000) != OK )
{
TerminateThread(m_Thread);
}
}
// start new switching thread:
m_Thread = StartNewThread( ThreadProc );
}
// this is a thread procedure:
static void ThreadProc()
{
DoActualSwitching();
NotifyListener();
}
private:
Thread m_Thread;
};
逻辑相当简单 - 如果用户在前一个切换完成之前启动新切换,我终止先前的切换(不关心“DoActualSwitching()”内部发生的事情)并启动新的切换。问题是,有时候,当终止线程时,我会松开“NotifyListener()”调用。
我想介绍一些改进,以确保每次调用NotifyListener(),即使线程被终止。有没有任何模式可以做到这一点?我只能想到另一个线程,它无限地等待切换器,如果切换器完成(正确或通过终止),它可以发出通知。但引入另一个线程似乎对我来说过于夸张。你能想到任何其他解决方案(p.s.平台是win32)吗?
谢谢!
答案 0 :(得分:2)
首先,你永远不应该致电TerminateThread
。调用TerminateThread
时无法知道哪个操作被终止,因此可能导致内存泄漏/资源泄漏/状态损坏。
要使您的线程可中断/取消,您将提供“取消”状态,该状态由线程本身检查。然后您的通知结束将始终有效。
答案 1 :(得分:1)
TerminateThread()在这里敲击线程,如果它在DoActualSwitching()里面,那就是它会死的地方,并且不会在该线程上调用NotifyListener()。这就是TerminateThread()所做的,并且没有办法使它的行为不同。
您正在寻找的是一种更优雅的方式来终止线程。如果没有关于您的应用程序的更多信息,很难建议最佳方法,但如果您可以编辑DoActualSwitching(),那么我将添加
if (WAIT_OBJECT_0 == WaitForSingleObject(m_ExitThreadEvent, 0))
break;
进入循环,并调用SetEvent(m_ExitThreadEvent)而不是TerminateThread()。当然,您需要创建事件并向该类添加句柄。如果你的模型建议一次只有一个切换线程,我会在这里使用autoreset事件,否则需要更多的代码。
祝你好运!