2

完了ソースがキャンセルされた場合、結果変数には何が返されますか?

async void SomeMethod()
{
   .....
   Run();
   var result = await GetResult();
   .....
}

Task<SomeResult> GetResult()
{
    return myCompletionSource.Task;
}

TaskCompletionSource myCompletionSource;

void Run()
{
     myCompletionSource= new TaskCompletionSource();
     TriggerSomeLongLastingLogicWhichWillCallCallBackBelow();

}

void SomeCallback()
{
     if (someCondition)
     {
         myCompletionSource.SetResult(<someResult>);
     }
     else
     {
         myCompletionSource.SetCancelled();
     }
}

このアプローチが正しいかどうかはよくわかりません。

  1. つまり、ステータス変数を使用して「someresult」のラッパーを作成するのではなく、タスクのステータスに依存することをお勧めしますか?
  2. キャンセルされたタスクを処理するには? 私はコールバックのファンではなく、タスクのステータスを分析できる ContinueWith を使用したソリューションが好きではありません。
4

1 に答える 1

4

完了ソースがキャンセルされた場合、結果変数には何が返されますか?

OperationCancelledExceptionキャンセルされたタスクを待っているときにコードをスローします。したがって、結果変数は決して設定されません。

try/catchブロックを使用して例外を処理できます。

async Task SomeMethod()
{
   try
   {
       .....
       Run();
       var result = await GetResult();
   }
   catch(OperationCancelledException)
   {
       // handle cancelled operation
   }
}

また、SomeMethodを返す必要があるため、Taskを返す必要があります。通常、メソッドをvoid返すのasyncはイベント ハンドラにのみ適していますvoidここで簡単にブログを書いています。

一般に、操作をキャンセル可能にしたい場合はCancellationToken、操作がチェックする必要がある を渡し、それを開始する他の操作に渡します。したがって、チェーンをずっと下ってコールバックに渡します。

CancellationTokenトークンがキャンセルされたときにキャンセルするコールバックを に登録することもできるTaskCompletionSourceので、メソッドでそれを行う必要はありません。

void Run()
{   
     var cts = new CancellationTokenSource();
     var myCompletionSource= new TaskCompletionSource();
     cts.Token.Register(() => myCompletionSource.SetCancelled());

     TriggerSomeLongLastingLogicWhichWillCallCallBackBelow(cts.Token);         
}

void SomeCallback(CancellationToken token)
{       
     // do some work
     ....

     token.ThrowIfCancellationRequested();

     if (someCondition)
     {
         myCompletionSource.SetResult(<someResult>);
     }
     else
     {
         myCompletionSource.SetException(new Exception("error occcured"));
     }
}
于 2015-04-22T07:01:21.657 に答える