1

順番に処理する必要があるアイテムのリストがあります (ただし、UI の応答性を維持するために別のワーカー スレッドで)。注意すべき重要な点は、これらのアイテムが長時間 (5 ~ 10 秒) 実行される可能性があることです。

Task<bool> currentTask = null;

foreach (var item in items)
{
    var currentItem = item;

    // Add a new task to the sequential task queue
    if (currentTask == null)
        currentTask = Task.Factory.StartNew<bool>(() => 
        { 
            return currentItem.ProcessItem(); 
        }, processCancelTokenSource.Token);
    else
        currentTask = currentTask.ContinueWith<bool>(t => 
        { 
            return currentItem.ProcessItem(); 
        }, processCancelTokenSource.Token);

    // Update UI after each task completes
    currentTask.ContinueWith(t =>
    {
        if (t.IsCanceled)
            currentItem.State = State.Cancelled;
        else
        {
            if (t.Result)
                currentItem.State = State.Complete;
            else
                currentItem.State = State.Failed;
        }
    },TaskScheduler.FromCurrentSynchronizationContext());
}

現在、CancellationTokenキューの処理をキャンセルするために を使用しています (「処理のキャンセル」ボタンがあります)。

問題は、現在実行中のタスクがキャンセルされないことです。が呼び出された場合CancellationTokenSource.Cancel()、キューで実行されるのを待っているすべてのタスクがキャンセルされ、それらの項目currentItem.Stateが に設定されState.Cancelledます。これは正しいです。問題は、キャンセル時に実行されていたタスクが、終了するまで実行され続け、その後State.Completeまたはに設定されることState.Failedです。これは 2 つの理由で理想的ではありません: (1) キャンセル後もタスクが実行中である、(2) がtrue でないState.Cancelledために状態が設定されてt.IsCanceledいない。

現在実行中のタスクを安全にキャンセル/停止する方法はありますか?

4

2 に答える 2

5

タスクは、適切なキャンセル パターンをサポートしています。CancellationTokenは単なるトークンです。実行中のコードを中断したり、スレッドを中止したりすることはありません。タスク本体でこのトークンを自分で確認する必要があります。

覚えておくべき 1 つのポイント: 現在のタスクをキャンセルしたい場合はCancellationToken.ThrowIfCancellationRequested、タスク本体から終了するだけでなく、メソッドを介してキャンセルしてください。

于 2012-09-13T10:25:00.180 に答える
3

タスクのキャンセルに関するこの msdn の記事を確認してください。http://msdn.microsoft.com/en-us/library/dd997396.aspx タスクの作業メソッド内でタスクがキャンセルされているかどうかを確認するだけです。チェック キャンセル コードをメソッドの重要な領域に配置します。それが役に立てば幸い!

于 2012-09-13T10:28:47.197 に答える