13

「CreateThread」関数でスレッドを作成しました。

このスレッドでは、「while(true)」ループ(入力を読み取る)があります。

今のところ、スレッドを閉じたいときは、「CloseHandle」関数を使用します。

これは正しいことですか?または、「while(true)」ループを終了してから「CloseHandle」関数を使用する必要がありますか?

ありがとう

4

3 に答える 3

19

CloseHandle()は、スレッドを破棄、終了、または中断するのではなく、ハンドル自体を破棄するだけです(したがって、スレッドを強制終了したり、スレッドを待機したりするためのハンドルはありません)。スレッドは引き続き正常に機能し(私はこれを多くの場合に利用しています)、スレッドを停止する唯一の方法は、スレッド関数(ThreadProc())を終了するか、スレッドを強制終了することです。

于 2012-06-27T12:44:46.593 に答える
6

一般に、これ(TerminateThreadの呼び出し)は、プロセス全体が終了するまで使用できないリソース(つまり、ファイル記述子)をスレッドが割り当てる可能性があるため、実行するのは悪いことです。さらに、CloseHandleはスレッドを停止しません。

スレッド内で長時間の操作を行う場合は、少なくとも

while(!ShouldExit)
{
     DoOneMoreIteration();
}

サイクル。このように、ShouldExitを1(または、C ++およびbool変数の場合は「true」)に設定し、このスレッドのハンドルでWaitForSingleObjectを呼び出して、スレッドが終了したことを確認することにより、スレッドを終了できます。

eranのコメントの場合:ShouldExitは「volatile」として宣言する必要があります。

何らかの入力(私が推測するコンソール)を待っている場合は、標準入力でノンブロッキング(「オーバーラップ」)I/Oを使用できます。

たとえば、次の質問を参照してください:Win32ファイルストリームで利用可能な入力を確認する

それは次のようなものになります

HANDLE h = GetStdHandle(STD_INPUT_HANDLE);

while(!ShouldExit) {
   if(WaitForSingleObject(h, FALSE, SomeTimeoutValue) == WAIT_OBJECT_0)
   {
      ... use std::cin - it has some input and won't block
   }
}

状況を改善するには(CPUのオーバーバーンを回避する)、WaitForMultipleObjectsを使用して、外部イベントでループの外側を中断します。

/// Global var
HANDLE SomeGlobalEvent;

/// ThreadProc():
HANDLE h[2];
h[0] = GetStdHandle(STD_INPUT_HANDLE);
h[1] = SomeGlobalEvent;

while(true) {
   DWORD which = WaitForMultipleObjects(2, h, FALSE, SomeTimeoutValue);
   if(which == WAIT_OBJECT_0)
   {
      ... use std::cin - it has some input and won't block
   } else
   if(which == WAIT_OBJECT_1)
   {
      // got the termination event
      break;
   }
}


/// "Main" thread:

SomeGlobalEvent = CreateEvent(NULL, false, false, NULL);

HANDLE hThread = _beginthread(ThreadProc, 4096, NULL);

 ....
 /// send termination signal
 SetEvent(SomeGlobalEvent);

 /// Wait for thread completion
 WaitForSingleObject(hThread);
于 2012-06-27T12:24:42.917 に答える
3

最良のことは、ドキュメントを注意深く読むことです。Win32APIは十分に文書化されています。

備考セクションのCreateThreadに関するMSDNから

スレッドの実行は、lpStartAddrパラメーターで指定された関数から始まります。この関数が戻る場合、DWORD戻り値は、ExitThread関数への暗黙の呼び出しでスレッドを終了するために使用されます。GetExitCodeThread関数を使用して、スレッドの戻り値を取得します。

その後、スレッドエントリ関数にその仕事をさせて終了させる必要があります。つまり、スレッドエントリ関数を返すループを終了します。

于 2012-06-27T12:24:50.370 に答える