8

マルチスレッドプログラムを書いています。

TerminateThreadとの違いは何ExitThreadですか?

WM_DESTROYこれは、受け取ったときの私のコード スニペットです。

void CleanAll()
{
    DWORD dwExit[MAX_THREAD];
    for(int i = 0; i < MAX_THREAD; i++)
    {
        GetExitCodeThread(hThread[i], &dwExit[i]);
        // I used ExitThread(dwExit[i]); previously
        TerminateThread(hThread[i], dwExit[i]);
        CloseHandle(hThread[i]);
    }
}

以前は使用ExitThread()していましたが、プログラムがタスク マネージャーに残っていたので、変更するTerminateThread()とタスク マネージャーからプログラムが消えてしまいました。

事前の説明は大歓迎です。

4

5 に答える 5

11

TerminateThread は、別のスレッドを強制的に終了させます。クリーンアップする機会がなく、そのトラックでスレッドが停止するため、絶対に呼び出すことは避けてください。これには、割り当てられたすべての CRT メモリが含まれます。

ExitThread は、現在実行中のスレッドが適切かつクリーンに停止するためのものです。上記で呼び出したときに、メイン (UI) スレッドを強制的に終了させ、実行中のスレッドをそのまま残した可能性があります。したがって、タスク マネージャーで証明されるように、プログラムはまだ実行されていました。スレッドが実際には終了していないため、GetExitCodeThread も失敗していた可能性があります。

しかし、スレッドを停止する正しい方法は、スレッドが終了する必要があることをクリーンな方法で明確に通知することです。 次に、メイン スレッドの終了を許可する前に、スレッドが単独で終了できるようにします。次の例では、グローバル フラグを使用して、終了する必要があることをスレッドに示しています。ただし、これは、スレッドが常にグローバル bool 状態をポーリングする機会があることを前提としています。もう 1 つのクリーンな方法は、各スレッドがイベント ハンドルで WaitForSingleObject を呼び出すようにすることです。イベント ハンドルが通知されると、スレッドはグローバル変数をチェックし、必要に応じて終了します。

bool global_Need_ToExit;  // use a bool or replace with an event handle the thread shoudl wait on

void CleanAll()
{
    //signal all threads to exit
    global_Need_ToExit = true;

    DWORD dwExit[MAX_THREAD];
    for(int i = 0; i < MAX_THREAD; i++)
    {
        // actually wait for the thread to exit
        WaitForSingleObject(hThread[i], WAIT_INFINITE);

        // get the thread's exit code (I'm not sure why you need it)
        GetExitCodeThread(hThread[i], &dwExit[i]);

        // cleanup the thread
        CloseHandle(hThread[i]);
        hThread[i] = NULL;
    }
}

DWORD __stdcall YourThreadFunction(void* pData)
{

    while (global_Need_To_Exit == false)
    {
        // do more work
    }

    return 0; // same as ExitThread(0);
}
于 2012-12-16T03:52:34.137 に答える
4

申し訳ありませんが、最も投票された回答は、「それ自体がきれいに停止する」ため、ExitThread を使用するように言っています。これは単に真実ではありません。ドキュメントには次のように記載されています 。ExitThread は、C コードでスレッドを終了するための推奨される方法です。ただし、C++ コードでは、デストラクタが呼び出される前、またはその他の自動クリーンアップが実行される前に、スレッドが終了します。したがって、C++ コードでは、スレッド関数から戻る必要があります。 フォーラムからのアドバイスに従って ExitThread を使用し、メモリ リークが一体どこから来ているのか何時間もかけて、これを難しい方法で学びました。ええ、それはC ++用ですが、それがこの質問に関するものです。そして実際には、Cの場合でも注意事項があります「静的 C ランタイム ライブラリ (CRT) にリンクされている実行可能ファイルのスレッドは、CreateThread と ExitThread ではなく、スレッド管理に _beginthread と _endthread を使用する必要があります。そうしないと、スレッドが ExitThread を呼び出したときに小さなメモリ リークが発生します。」 結果を認識せずに ExitThread を使用しないでください。

于 2016-10-21T10:12:49.410 に答える
2

スレッドが完了したら、プロセスは終了するはずですか? あなたが説明した問題には多くの説明があるかもしれません。プロセス全体を終了したい場合は、 を呼び出すだけExitProcessです。

問題TerminateThreadは、メモリ リークが発生する可能性が非常に高いことです。スレッドの状態も、割り当てられたリソースも気にしません。同期の方法によっては、デッドロックが発生することもあります。つまり、正常に終了しません。

スレッドを終了する最善の方法は、明示的に終了しないことです。TerminateThreadnorExitThreadを呼び出さないでくださいreturn。スレッドの関数から呼び出してください。アトミック フラグを使用するか、イベント (または別の同期メソッド) を起動して、スレッドがいつ終了するかを通知する必要がある場合があります。次に、スレッドはそのフラグ (またはイベント) を定期的にチェックし、戻る (終了する) 前にすべてのリソースの割り当てを解除する必要があります。

于 2012-12-16T03:52:14.137 に答える
0

最終的には、各スレッドをミニ プロセスのように表示する必要があります (これが内部の処理です)。正常にシャットダウンするには、追加のインフラストラクチャを配置して、メイン スレッドに停止を指示できるようにする必要があります。

これを正しく行うための最も簡単な方法は、POSIX の発明者が早い段階で見つけ出し、OS で直接公開するシグナリング システムです。このようなシステムの実例として最も優れているのは、米国の郵便局です。すべてのエージェントには、他のアドレスからメール (シグナル) を送受信できる固有のアドレスがあり、シグナルを受信したときに何をするかを決定するのはエージェント次第です。一部は情報またはジャンクであるため無視されますが、他のものは優先度が高く、危険を冒して無視します.

コード レベルでは、それをうまく機能させるために次のものが必要です (画像処理プログラム用にいくつか作成しました)。
1) 抽象的な「イベント」または「コントロールシグナル」オブジェクト。適切であれば、デフォルトの Windows イベントまたは Linux シグナルを自由に使用してください。
2) ある種の「パイプ」: OS には、多くの場合、文字通りのカーネル プリミティブがあり、パイプを呼び出して、一方がデータを取り出し、もう一方がデータを挿入できるようにします。この男は通常、プロセス内の通信には過剰です。 need は概念的に同等です。
3) パイプからシグナルを取得し、それらに作用するスレッド内のコード。4) すべてのスレッドが認識する「停止」または「キャンセル」シグナル。

もちろん、タスクキルまたは CTRL-C を使用してプロセスを強制終了できるのと同じように、TerminateThread を使用してスレッドを強制的に中止することもできます。ExitThread は、(4) で説明したように、クリーンなシャットダウン シグナルを作成するための Windows 固有の方法ですが、それを機能させるには、while-loop & "WaitForSingleObject" (3) と Windows 固有のハンドル (2) が必要です。

于 2014-01-22T21:33:02.497 に答える
0

SingleWaitObjects または QueueUserAPC を使用できますが、スレッドがこれらの非同期オブジェクトをチェックするために停止するか、最後にいずれかを待機してスレッドを正常に終了することを確認する必要があります.. Linux では、シグナルを使用できます

于 2012-12-16T04:33:56.210 に答える