2016-11-23 20 views
5

オブジェクトのリスト<>を返すメソッドがあります。このメソッドは実行に時間がかかります。リスト<MyObject>にはGetAwaiterの定義が含まれていません

private List<MyObject> GetBigList() 
{ 
    ... slow stuff 
} 

このメソッドは、4つまたは5つのソースから呼び出されます。だから、私は非同期を試してみると思って、このリストが構築されている間、物事を動かすのを待っています。

List<MyObject> does not contain a definition for GetAwaiter, and no extension method 'GetAwaiter' accepting a first argument of type List<MyObject> could be found.

私は何をしないのです。私はこのエラーを取得する

var resuls = await resultsTask; 

:この行に、

public async Task<List<MyObject>> GetBigListAsync() 
{ 
    var resultsTask = GetBigList(); 
    var resuls = await resultsTask; 
    return resuls; 
} 

しかし:私は、このメソッドを追加しましたか?

+1

あなたのコード例では、タスクのいずれかの使用では表示されません。 GetBigListメソッドもasyncとしてマークされていないので、そのメソッドからの結果を待つことはできません。タスク<リスト> GetBigList() –

+0

試みは、非同期操作に同期動作をしない待って、覚えておいてください。既存の*非同期操作の継続として現在のメソッドの残りの部分にサインアップします。待っているのは*非同期*を管理することであり、作成するのではありません。同期操作を非同期にするには、その操作を行う方法を見つけなければなりません。 – Mate

+2

非同期 –

答えて

9

resultTaskGetBigList()から返されたリストにすぎないため、そこには何も起こりません。あなたは何ができるか

Task.Runを使用してスレッドプール上の別のスレッドにタスクをオフロードし、awaitable Taskオブジェクトを返します:

// Bad code 
public Task<List<MyObject>> GetBigListAsync() 
{ 
    return Task.Run(() => GetBigList()); 
} 

例を超える最高のは、あなたがやろうとしていたものと一致しますが、それがされベストプラクティスではない。 GetBigList()を本質的に非同期にするか、実際には方法がない場合は、呼び出しコードに対する別のスレッドでコードを実行するかどうかの決定を残して、実装内でこのコードを非表示にしないでください。呼び出し元のコードがすでに非同期で実行されている場合、別のスレッドを生成する理由はありません。 This articleはこれをより詳細に説明している。

5

あなたはaysnc-awaitの初心者だと思います。 async-awaitがどういうことを理解するのが本当に助けになったのは、Eric Lippertによって与えられたレストランの類推です。this interview.真ん中で非同期待ちが検索されます。

ここでは、料理人が何かを待たなければならない場合、何もしない代わりに、彼は周りを見回してその間に何か他のことをすることができるかどうかを調べることを説明します。

Async-awaitも同様です。ファイルを読み込むのを待つ代わりに、返すデータベースクエリー、ダウンロードするWebページ、スレッドが呼び出しスタックを上って呼び出し元が待機していないかどうかを確認し、待機するまでそれらの文を実行します。スレッドが待っていると、スレッドはコールスタックに再度アクセスして、呼び出し元の1人が待機していないかどうかを確認します。ファイルが読み込まれたり、クエリが終了したなどしばらくしてから、待機した後のステートメントが実行されます。

通常、あなたの大きなリストを読んでいる間、あなたのスレッドは待っている代わりに非常に忙しいでしょう。何かをするために別のスレッドを注文することがあなたのリストを読むために必要な時間を改善することは確かではありません。両方の方法の測定を検討してください。

One reason to use async-await, even if it would lengthen the time needed to read the big list, would be to keep the caller (user interface?) responsive.

あなたの関数の非同期を作るために、あなたは次のことを行う必要があります。

  • あなたの関数呼び出した場合は代わりにTResultリターンTast<TResult>の代わりに、voidリターンTask
  • 非同期(async)関数を宣言他の非同期機能は、awaitの代わりに返されたタスクを思い出し考えるあなたがする必要がある他の有用なものを行うとawait結果が必要なときのタスク。
  • あなたが本当に別のスレッドがビジーなものを行うようにしたい場合。

    Task.Run(()=> GetBigList())

を呼び出し、あなたが結果を必要なときに待っています。

private async Task<List<MyObject>> GetBigListAsync() 
{ 
    var myTask = Task.Run(() => GetBigList()); 
    // your thread is free to do other useful stuff right nw 
    DoOtherUsefulStuff(); 
    // after a while you need the result, await for myTask: 
    List<MyObject> result = await myTask; 

    // you can now use the results of loading: 
    ProcessResult(result); 
    return result; 
} 

もう一度:他のスレッドが(応答性のUIを維持するように)リストをロードしている間、あなたが行うことが有益な何もない場合は、より高速であれば、この、または少なくとも測定を行いません。 、これまでにその有用ステファン・クリアリーによって、 をAsync await - - 私は非同期待つ理解する助け

その他の記事は たと、もう少し高度:Async-Wait best practices

関連する問題