2017-12-11 3 views
0

私は特定のユースケースで動作するようにC#でタスクを取得しようとしていますが、タスクの継続オプションがタスクの流れに与える影響を理解していません。取り消し自体を起動せずに取り消されたタスクを処理するには?

私がやっていることは、ContinueWithと連鎖している一連の作業を取得することです。 - > B - > C - > D

しかし、私はイベントで短絡するオプションこのエラーを含めたいので、それは次のようになります

A:これは、このようになります。 :

A - > B - > C - > D - > X

だから私はContinueWith機能のそれぞれのタスク継続オプションとして "OnlyOnRanToCompletion" を置きます。次に、取り消しをキャッチしてエラーを返すために、タスクの継続オプションを「OnlyOnCanceled」に設定してチェーンの最後に最終タスクを配置します。

問題は、この最後のブロックがヒットした場合、継続オプションが満たされず、元の一連のタスクが決してキャンセルされなかった場合でもタスクがキャンセルされるように設定されることです。

AからDが実行され、そのうちの1つがキャンセルされた場合は残りをスキップしてXを実行します。AからDが完了すると、タスクはキャンセルされません。解決策は、任意の数の継続をサポートする必要があり、LINQ.Expressionsを使用して作成されるため、async/awaitを使用することは、創造的に行われていない限り、おそらく飛ぶことはありません。

これを示すいくつかのサンプルコードは次のとおりです。

var cts = new CancellationTokenSource(); 
var token = cts.Token; 

var t = Task.FromResult(1) 
    .ContinueWith(
    x => x.Result + 1, 
    token, 
    TaskContinuationOptions.OnlyOnRanToCompletion, 
    TaskScheduler.Default) 
    .ContinueWith(
    x => x.Result + 1, 
    token, 
    TaskContinuationOptions.OnlyOnRanToCompletion, 
    TaskScheduler.Default) 
    .ContinueWith(
    x => -1, 
    token, 
    TaskContinuationOptions.OnlyOnCanceled, 
    TaskScheduler.Default); 

ここで予想される動作は、3を返すようになり、ステータスが完了していません。

実際には、タスクがキャンセルされます。

どうすればよいですか?

また、私は、LINQ.Expressionsからコンパイルされたものの中でTPLをピギーバックし、例外を投げずに非同期で評価し、最後にエラーを処理できるようにすることを目標にしているため、私はasyncを使用できません。

+0

非同期ワークフローを構築するには、「ContinueWIth」ではなく、実際には「await」を使用する必要があります。 'await'は使用するのがずっと簡単であり、多くの分野、特にここで見ているように、エラー処理に関しては、より望ましいデフォルト動作があります。 – Servy

+0

私はこれを質問に加えるべきです - 私ができたら、私はできますが、できません。私は非同期に実行する必要がある小さなプログラムをコンパイルするためにLINQ.Expressionsを使用していますが、そのアクセス権はありません。 –

+0

私は強く疑いますが、実際の問題に関する十分な情報を提供しない場合、人々はあなたに良い解決策を与えることはできません。 – Servy

答えて

1

はそれを考え出した - に関係なく、前回の継続が完了したか否かの実行するための最後の継続を取得し、キャンセルにステータスを設定せずに、このです:

  1. 変更に前回の続きの継続オプションをTaskContinuation.Noneを実行すると、常に実行されるため、完了した状態でここに到着すると取り消されません。

  2. 取り消しトークンを最後の継続に渡さないでください。取り消された取り消しトークンを渡すと、トークンなしで実行した場合に継続を取り消す効果があるようです。

0

は、この動作の説明についてはContinueWithのための注釈を参照してください:現在のタスクが完了するまで

返されたタスクの実行をスケジュールできません。 continuationOptionsパラメーターで指定した条件が満たされない場合、継続タスクはスケジュールされているのではなくキャンセルされます。

最後のContinueWithコールの条件が満たされなかったため、そのコールから返されたTaskがキャンセルされました。

関連する問題