2017-08-14 10 views
2

私は一緒にチェーンに私が作成したいくつかの非同期メソッドを試みていると私はこれがチェーン非同期メソッド

をどのように機能するかについての私の部分にいくつかの基本的な誤解はここに私のコードの表現がありますされると信じて:

public async Task<bool> LoadFoo() 
{ 
    return await Foo.ReadAsync("bar").ContinueWith((bar) => 
    { 
     Foo.ReadAsync("baz").ContinueWith((baz) => 
     { 
      Foo.ReadAsync("qux").ContinueWith((qux) => 
      { 
       return true; 
      }); 

      return true; 
     }); 

     return true; 
    }); 
} 

public void LoadEverything() 
{ 
    LoadFoo().ContinueWith((blah) => 
    { 
     OtherLoadMethod(); 
    }); 
} 

LoadFoo( "bar"、 "baz"、 "qux")のReadAsyncメソッドがすべて実行され、完了した後、それらがすべて完了した後、LoadEverything()が呼び出されたときに、 LoadEverythingは、 "bar"、 "baz"、 "qux" ReadAsyncメソッドが終了するまでOtherLoadMethod()が実行されないように実行されます。

私が実際に見ているのは、LoadFooが呼び出された後、OtherLoadMethodがLoadFooの最後の補完に達する前に実行を開始することです( "qux" ReadAsyncの続行)。

ここで私の誤解を解決するのに役立つ人はいますか? ReadAsync( "qux")が終了してtrueを返すまで、OtherLoadMethodの実行がなぜ待たないのですか?

+0

:IMHO、あなたのコードは、(あなたの代わりにTaskTask<bool>を返している理由戻り値がしかtrueであるから、それは、明確ではないのですが、私は自分でその部分を把握することができます仮定)次のようになります'ContinueWith'を使わないでください。代わりに 'await'を使用してください。 –

答えて

8

ReadAsync( "qux")が終了しtrueを返すまで、OtherLoadMethodの実行を待たないのはなぜですか?

awaitが動作するためです。あなたが登録する続行はそれだけです:継続。現在のメソッドでは同期的に実行されません。現在のタスクがを完了したときにというフレームワークに伝えている場合は、継続を実行する必要があります。 ContinueWith()によって返されたTaskオブジェクトは、発生した場合に完了を観察することができます。 ContinueWith()メソッドが継続が実行されるまでブロックされた場合は、Taskオブジェクトを返す必要はありません。

同様に、LoadFoo()メソッドによって返されたTask<bool>は、返すawait...ContinueWith()を含むメソッドの全体的な完了を表します。このメソッドは継続の完了前に戻り、呼び出しが完了するまで待機する必要がある場合、呼び出し元は返されたタスクを使用することが期待されます。

私は最初にContinueWith()を使用している理由を理解できません。あなたは明らかに継続を扱う現代的で慣用的な方法であるawaitにアクセスすることができます。

public async Task<bool> LoadFoo() 
{ 
    await Foo.ReadAsync("bar"); 
    await Foo.ReadAsync("baz"); 
    await Foo.ReadAsync("qux"); 

    return true; 
} 

public async Task LoadEverything() 
{ 
    await LoadFoo(); 
    await OtherLoadMethod(); 
} 
+0

Peterに感謝します。ちょうど私が正しく理解していることを確認するために、スレッドが正しくブロックされないのを待っていますか? "継続メソッドを使用する場合(たとえば、メソッドの戻り値を使用する必要がある場合など)、このコメントを理解したかったのです。 "メソッドは継続が完了する前に戻り、呼び出し元は続行が完了するのを待つ必要がある場合は、返されたタスクを使用してください。 LoadFoo()を呼び出すことはありません。ContinueWith(...)は、継続が完了するのを待っている呼び出し元ですか? –

+0

_ "awaitはスレッドをブロックしません" _ - 正しいです。 'await'は、メソッドが_may_を返す(それが待っている式がすでに完了していない場合)メソッドのポイントをマークし、待つことが完了した時点でそのポイントを再開(続行)します。スレッドは、その時点で呼び出し元に戻るか、現在のメソッドの実行を続行します。どちらの方法でも、スレッドはブロックされていません。 –

+0

_ "LoadFoo()を呼び出しませんでした。続行が完了するのを待っている呼び出し元はContinueWith(...)ですか?そこに待つことはありません。 'ContinueWith()'は単に継続を登録してから、継続の完了を表すタスクオブジェクトを返します(元のタスクが完了するまで完了できません)。 –

関連する問題