web-dev-qa-db-ja.com

C#で複数のタスクをキャンセルする正しい方法は何ですか

4つのタスクを生成するボタンがあります。同じボタンがキャンセルボタンに変わり、これをクリックすると4つのタスクすべてがキャンセルされます。 4つのタスクすべてに同じキャンセルトークンを渡し、IsCancelRequestedについて同じトークンをポーリングする必要がありますか? createlinkedtokensource のmsdnドキュメントを読んだ後、混乱しています。これは通常どのように行われますか?ありがとうございました

更新:Task.WaitAll()は、すべてのタスクが実行を完了するまで待機します。同様に、共有キャンセルトークンソースがキャンセルに設定された後、すべてのタスクがいつキャンセルされたかを知る方法。

23
Gullu

ええ、単一のCancellationTokenを使用することについてあなたが言ったことは正しいです。単一のCancellationTokenSourceを作成し、そのCancellationTokenをすべてのタスクに使用できます。タスクは、キャンセルについてトークンを定期的にチェックする必要があります。

例えば:

_const int NUM_TASKS = 4;

CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;

Task[] tasks = new Task[NUM_TASKS];
for (int i = 0; i < NUM_TASKS; i++)
{
    tasks[i] = Task.Factory.StartNew(() =>
    {
        while (true)
        {
            Thread.Sleep(1000);
            if (ct.IsCancellationRequested)
                break;
        }
    }, ct);
}

Task.WaitAll(tasks);
_

ボタンはcts.Cancel();を呼び出してタスクをキャンセルできます。

質問の更新のための更新:

あなたが求めることをするためのいくつかの方法があります。 1つの方法は、_ct.IsCancellationRequested_を使用して、スローせずにキャンセルを確認してから、タスクを完了できるようにすることです。その後、すべてのタスクがキャンセルされると、Task.WaitAll(tasks)が完了します。

その変更を反映するようにコードを更新しました。

26
Matt

はい、それがあなたの意図であるならば、あなたは同じトークンを渡し、これを使ってすべてのタスクを一度にキャンセルするべ​​きです。

1
TheCodeKing
const int NUM_TASKS = 4;

CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;

Task[] tasks = new Task[NUM_TASKS];
for (int i = 0; i < NUM_TASKS; i++)
{
    tasks[i] = Task.Factory.StartNew(() =>
    {
        while (true)
        {
            Thread.Sleep(1000);
            if (ct.IsCancellationRequested)
                break;
        }
    }, ct);
}

Task.WaitAll(tasks);
0