1

こんにちは、私はそのようなコードでスレッドを開始します:

    Thread[] thr;
    private void button1_Click(object sender, EventArgs e)
    {
        decimal value = numericUpDown2.Value;
        int i = 0;
        threads_count = (int)(value);
        thr = new Thread[threads_count];
        for (; i < threads_count; i++)
        {
            thr[i] = new Thread(new ThreadStart(go));
            thr[i].IsBackground = true;
            thr[i].Start();
        }
    }

私の条件が真になった場合にそれらをすべて停止する方法

4

6 に答える 6

21

多くの答えは、スレッドを中止すると言っています。 緊急事態でアプリケーションをシャットダウンする場合を除いて、スレッドを中止しないでください

CLRは、その内部データ構造がスレッドの中止によって破損しないことを保証します。これは、スレッドアボートに関してCLRによって行われる唯一の(*)保証です。具体的には次のことを保証するものではありません。

  • スレッドが実際に中止すること。スレッドは、終了しないように固まる可能性があります。
  • CLR自体にないデータ構造は破損しません。重要な操作の途中でスレッドが異常終了すると、BCLデータ構造またはユーザーデータ構造が任意に一貫性のない状態になる可能性があります。これにより、後で不思議なことにプロセスがクラッシュする可能性があります。
  • そのロックは解放されます。スレッドを中止すると、ロックが永久に保持されたり、デッドロックが発生したりする可能性があります。

はっきりしない場合:スレッドを中止することはめちゃくちゃ危険であり、すべての選択肢が悪い場合にのみそうする必要があります。

では、スレッドを起動してからクリーンにシャットダウンしたい場合はどうでしょうか。

まず、そうしないでください。そもそもスレッドを開始しないでください。キャンセルトークンで開始し、Task<T>シャットダウンする場合は、キャンセルトークンを通知します。

スレッドを開始する必要がある場合は、メインスレッドと作業スレッドが「この時点でクリーンにシャットダウンしてほしい」とクリーンかつ安全に通信できるメカニズムが存在するようにスレッドを開始します。

それを行う方法がわからない場合は、その方法を学ぶまでマルチスレッドコードの記述を停止してください。


(*)これは小さな嘘です。CLRは、スレッドの中止と、制約された実行領域や最終的にブロックなどの特別なコード領域との相互作用に関しても一定の保証を行います。

于 2013-02-11T17:52:41.837 に答える
2

残忍な方法 (非推奨) - Thread.Abortメソッドを使用してスレッドを中止します。このメソッドは、スレッドで ThreadAbortException を発生させます。このような:

foreach(Thread thread in thr)
    thread.Abort();

しかし、より良い方法は、キャンセルについてスレッドに通知し、正しくジョブを終了させることです。.Net 4 タスクで簡単に実行できます。

Task[] thr = new Task[threads_count];
var source = new CancellationTokenSource();

for (int i = 0; i < threads_count; i++)
{
    thr[i] = Task.Factory.StartNew(go, source.Token);
}

// later, when condition is met
source.Cancel();

キャンセルは次のようになります。

private static void go(object obj)
{
    CancellationToken token = (CancellationToken)obj;
    while (true)
    {
        if (token.IsCancellationRequested)
            return;

        // do some work
    }
}
于 2013-02-11T17:27:50.203 に答える
2

を使用しCancellationTokenて、操作を停止するタイミングを通知できます。

  1. CancellationTokenSourceボタン クリック ハンドラで初期化する型のインスタンス フィールドとして を作成します。

  2. バックグラウンド メソッドでトークン ソースのIsCancellationRequestedプロパティを定期的にチェックするか、キャンセルされた場合に例外をスローする場合は呼び出します。TokenThrowIfCancellationRequested()

  3. Cancelトークン ソースでスレッド呼び出しを停止する場合。

于 2013-02-11T17:46:15.583 に答える
1

スレッドを正常に終了する方法を知りたい場合は、MSDN で次の例を参照することをお勧めします。

using System;
using System.Threading;

public class Worker
{
    public void DoWork()
    {
        while (!_shouldStop)
        {
            Console.WriteLine("worker thread: working...");
        }
        Console.WriteLine("worker thread: terminating gracefully.");
    }
    public void RequestStop()
    {
        _shouldStop = true;
    }
    // Volatile is used as hint to the compiler that this data
    // member will be accessed by multiple threads.
    private volatile bool _shouldStop;
}

public class WorkerThreadExample
{
    static void Main()
    {
        Worker workerObject = new Worker();
        Thread workerThread = new Thread(workerObject.DoWork);
        workerThread.Start();
        Console.WriteLine("main thread: Starting worker thread...");

        while (!workerThread.IsAlive); // Loop until worker thread activates

        // Put the main thread to sleep for 1 millisecond to
        // allow the worker thread to do some work:
        Thread.Sleep(1);

        workerObject.RequestStop();

        // Use the Join method to block the current thread 
        // until the object's thread terminates.
        workerThread.Join();
        Console.WriteLine("main thread: Worker thread has terminated.");
    }
}
于 2013-02-11T17:31:59.830 に答える
-5

単純な答えは、スレッドの Abort() メソッドを使用することですが、コードでは実際にはどのような状態かが明確になりません。

ループテストと条件は何ですか? なぜスレッドを中止する必要があるのですか? これにアプローチするより良い方法があるかもしれないので、私は尋ねています

于 2013-02-11T17:30:37.323 に答える