1

子孫を扱うとき、TThread私は基本的に選択肢があります:

  • 子孫オブジェクトを削除しますが、設定FreeOnTerminateしませんtrueTThreadNULL
  • 手動で行い、自分で削除するという混乱をすべて経験します

基本的に必要なのは、スレッドが実行されているかどうかを判断する方法なので、次のことを行いました。

//------------------------------------------------------------------------------
// 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 を初期化または再起動する前に、実行が完了しているかどうかを知る必要があるだけです。

  • スレッドを終了せずに再起動できますか (プログラムが終了するまでオブジェクトを削除する必要はありません)。

4

2 に答える 2

1

スレッド内で while ループを実行し、通知されたときに 1 回実行できるように上部で待機することは、継続的にスレッドを作成/終了/破棄し、関連するマイクロ管理を行うよりも非常に好ましいため、他の方法は正気ではありません。

スレッドを作成し、一番上に待機して while ループを入れ、実行するように信号を送ります。絶対に強制されない限り、スレッドをまったく終了しません。

死の呼び声:

TThread.WaitFor
TThread.Synchronize
TThread.Terminate

これらを使用しないように一生懸命努力してください。

簡単な例:

TmyThread=class(TThread);
private;
  mySimpleEvent:TSimpleEvent;
public
  constructor create;
  procedure go;
end;

constructor TmyThread.create;
begin
  inherited create(true);
  mySimpleEvent:=TSimpleEvent.Create;
  resume;
end;

procedure TmyThread.go;
begin
  mySimpleEvent.SetEvent;
end;

procedure TmyThread.Execute;
begin
  while mySimpleEvent.WaitFor(INFINITE) do
  begin
    mySimpleEvent.ResetEvent;
    //code to do your stuff
  end;
end;
于 2013-04-04T20:22:13.770 に答える