2016-09-23 10 views
0

私は奇妙な行動を(私の目で)理解しようとしています。いくつかの非同期メソッドへの呼び出しがあり、その結果を取得したい。 falseでありStatusWaitingForActivationである。このシナリオResultTask.ContinueWith()を理解しようとしています

var deleteTask = Task.Run(() => DeleteIndexAsync(localItem)) 
    .ContinueWith(t => 
    { 
    //handle and log exceptions  
    }, TaskContinuationOptions.OnlyOnFaulted); 

if (!deleteTask.Result) 

Task<bool>を返すDeleteIndexAsync)。

このコードは、私が

var deleteTask = Task.Run(() => DeleteIndexAsync(localItem)); 
    deleteTask.ContinueWith(t => 
    { 
    //handle and log exceptions 
    return false; 
    }, TaskContinuationOptions.OnlyOnFaulted); 

    if (!deleteTask.Result) 

何をしたいん一方で誰かが理由を説明できますか? Taskの代わりにasync/awaitを使用することはできますか?

編集:あなたが呼び出しをチェーンした場合

var deleteTask = Task.Run(() => ThrowEx()); 
    bool errorOccurred = false; 
    deleteTask.ContinueWith(t => 
    {   
    errorOccurred = true; 
    }, TaskContinuationOptions.OnlyOnFaulted); 

    if (errorOccurred) 
    { 
    return true; 
    } 

答えて

2

、最初の例のように、あなたはdeleteTask変数に代入された値は実際には二Taskです。これは、最初のタスク(DeleteIndexAsyncを呼び出すタスク)の失敗時にのみ実行されるはずのものです。

これは、Task.RunTask.ContinueWithの両方が返され、返されるのはTaskです。これは、最初の例ではStatus == WaitingForActivationを取得する理由を説明します。最初のスニペットでは、deleteTask.Resultにアクセスすると例外がスローされます。 DeleteIndexAsyncが投げた場合は、t.Exceptionにアクセスしていない限りオリジナルの例外を含むAggregateExceptionになります。そうでないと、「操作がキャンセルされました」と表示されます。これは、条件付きでスケジュールされたタスクの結果を取得しようとするためです。条件は満たされませんでした。あなたが切り取ら含む方法を行った場合

asyncあなたは(テストしていません)このようにそれを行うことができます:

bool success = false; 
try 
{ 
    success = await DeleteIndexAsync(localItem); 
} 
catch (Exception) {} 

if (!success) 
{ 
    //TODO: handler 
} 

を質問編集について:

役立つはずキャプチャ変数を使用しますが、あなたの現在のソリューション競合状態を引き起こす。 - この例では、Runの間で行うことができ、作業を簡素化していない限り

var deleteTask = Task.Run(() => ThrowEx());  

try 
{ 
    deleteTask.Wait(); 
} 
catch (Exception ex) 
{ 
    return true; 
} 

が、あなたはすぐに結果を待っているので、この時点であなたは、完全に非同期呼び出しをドロップすることができます。この場合、次のように行う方が良いでしょうおよびWait

+0

私はエラーが発生したかどうかを判断するためにtask.Resultをチェックするといいと思います。タスクにアクセスする.Resultはここで例外をスローします...また、Faultedフラグは、例外がスローされた場合でも常に偽です。 – user3292642

+0

@ user3292642私は理解しているとは思わない?例外を飲み込むには、 'Exception'プロパティにアクセスする必要があります。 – slawekwin

+0

私は例外を飲みたくありません。私はすでにcontinuewithメソッドでそれを記録しています。ロギングが終了した後、例外がスローされた場合に戻ってきたいと思いますが、方法はわかりません。ステータスをチェックすることもオプションではありません。 – user3292642

2

私はいくつかの非同期メソッドを呼び出し、その結果を取得したいと思います。

The best way to do this is with await, not Result

誰かが理由を説明できますか?

最初の例では、deleteTaskTask.Runから返されたタスクです。 2番目の例では、deleteTaskContinueWithから返されたタスクです。DeleteIndexAsyncが例外をスローしない限り、このタスクは実際には実行されません。

ここではタスクの代わりにasync/awaitを使用できますか?

はい、これが最良の方法です。非同期コードで作業する場合は、常にuse await instead of ContinueWithにする必要があります。

bool deleteResult; 
try 
{ 
    deleteResult = await Task.Run(() => DeleteIndexAsync(localItem)); 
} 
catch (Exception ex) 
{ 
    //handle and log exceptions 
} 
if (!deleteResult) 
    ... 

あるいは、DeleteIndexAsyncが非同期であるように見えることから、Task.Runを除去することがより適切であろう:この場合、TaskContinuationOptions.OnlyOnFaultedはあなたがawaitcatchブロックで継続コードを置くべきであることを意味

bool deleteResult; 
try 
{ 
    deleteResult = await DeleteIndexAsync(localItem); 
} 
catch (Exception ex) 
{ 
    //handle and log exceptions 
} 
if (!deleteResult) 
    ... 
関連する問題