当TThread
后代的工作我基本上有一个选择:终止线程变量,并将其设置为NULL
- 设置
FreeOnTerminate
到true
它删除我的TThread
后代对象,但不会将其设置为NULL
- 做手动,并通过自己删除它的所有烂摊子
我基本上需要的是一种方式来确定线程是否正在运行,所以我做了以下:
//------------------------------------------------------------------------------
// Thread descendant
//------------------------------------------------------------------------------
class TMyThread : public TThread
{
private: UnicodeString StatusLine; // Used for Synchronize function
void __fastcall UpdateGUI();
protected: virtual void __fastcall Execute();
public: __fastcall TMyThread();
};
//------------------------------------------------------------------------------
TMyThread *MyThread;
//------------------------------------------------------------------------------
// Thread constructor
__fastcall TMyThread::TMyThread() : TThread(true)
{
FreeOnTerminate = false;
Priority = tpNormal;
}
// Synchronize function for Form1
void __fastcall TMyThread::UpdateGUI()
{
Form1->Label1 = StatusLine;
}
// Execute code
void __fastcall TMyThread::Execute()
{
Sleep(2000);
StatusLine = "I am almost done!";
Synchronize(&UpdateGUI);
}
// Thread terminate, delete object, set to NULL
void __fastcall TForm1::ThreadTerminateIfDone(TMyThread *T)
{
if (T != NULL && WaitForSingleObject(reinterpret_cast<void*>(T->Handle),0) == WAIT_OBJECT_0)
{
T->Terminate();
T->WaitFor();
delete T;
T = NULL;
}
}
// And initialization part which needs to check if thread is already running
void __fastcall TForm1::StartOrRestartThread(TObject *Sender)
{
// Remove old thread if done
ThreadTerminateIfDone(MyThread);
// Check if thread is running - NULL = not running and terminated or uninitialized
if (MyThread == NULL)
{
MyThread = new TMyThread();
MyThread->Start();
}
else
{
Application->MessageBox(L"Thread is still running please wait!", L"Error", MB_OK);
}
}
此代码按原样运行。我的问题是:
有没有办法简化这个?我需要在完成后将
MyThread
设置为NULL,以便在下次调用启动/重新启动之前,对象不在周围。这不能用FreeOnTerminate
设置为true来完成,因为它会删除对象。我只能尝试访问对象,然后生成异常(我可以捕捉,但它是愚蠢的)。我真的只需要知道在我初始化或重新启动MyThread之前是否执行了执行。我可以重新启动线程而不终止它(我不需要在程序结束之前删除对象) - 如果我启动线程,我会得到“无法在运行或挂起的线程上调用启动”异常。
我确实尝试过,但是您确定可以将MyThread设置为ThreadTerminated事件内部的NULL吗?如果对象尚未释放,是否会导致访问冲突? – Coder12345 2013-04-04 20:44:37
@ Coder12345:是的,我确定。 'OnTerminate'事件是通过'Synchronize()'触发的,直到'OnTerminate'事件处理程序退出之后,线程对象才会被释放。 – 2013-04-04 20:46:45
谢谢雷米,很好的答案,一切都很好。 – Coder12345 2013-04-04 21:27:59