2016-06-16 10 views
1

今、私のメソッドは次のようになります。ビジネスで私はビジネス/サービス/アプリケーション層の間で非同期待機を使用する必要があります

プロダクトマネージャークラスのサービスで

public static async Task<List<ProductItem>> GetAllProducts() 
{ 
    var context = GetMyContext(); 
    return await context.Products.select(x => 
    new ProductItem{ //create item}) 
    .ToListAsync(); 
} 

ProductServiceクラス。

public async Task<List<ProductItem>> GetAllProducts() 
{ 
    return await ProductManager.GetAllProducts(); 
} 

ProductController in application。

public async Task<ActionResult> Index() 
{ 
    var ps = new ProductService(); 
    var productsAsync = ps.GetAllProducts(); 
    // Do other work. 
    var products = await productsAsync; 
    return View(products); 
} 

このアプリケーションは、高い使用率を取得し、 は完全に間違ってそれをやって、この方法は何ですか? 私はあらゆる方法を待つべきですか? これは、awaitが呼び出されるたびに新しいスレッドを開始しますか?

+0

'await'は何かが完了するのを待っています。あなたのメソッドでタスクの結果を必要としない場合は、それを待つ必要はありません。 'GetAllProducts'は単に' ToListAsync'の結果を返すべきです –

+0

"これはawaitが呼び出されるたびに新しいスレッドを開始しますか?"これはよくある誤解です - 「待って」は何も開始しません。それがすることは、*忠実に*タスクやタスクのようなオブジェクトが既に開始されているものを終えるのを待つことです。* 'Task'がそれを達成している(スレッドの開始、I/Oのキューイングなど)方法は、あなたのコードを' Task'に戻したメソッドの責任です。 –

+0

まず、ここの 'ProductService'は無意味です。サービスメソッドで作業をするか、単に 'ProductManager'を直接使用してください。ここでは、2つの重複したAPIを管理するだけです。次に、 'var products = ps.GetAllProducts();'を待ちます。タスクを変数に最初に保存する必要はありません。最後に、以下の@PanagiotisKanavosのアドバイスに耳を傾けます:メソッド自体がTaskを返す場合は、内部に何かを待ってはいけません。タスクを返すだけです。 (実際には、そのメソッドのTaskの結果で何かを行う必要がある場合を除きます)。 –

答えて

3

このアプリケーションは高い使用率を示していますが、これは完全に間違っていますか?

いいえ。それは私によく見えます。

すべてのメソッドを待つ必要がありますか?

はい。最初にawaitProductManager)を入れると、その発信者はawaitとなり、発信者はawaitとなり、コントローラーの動作方法までになります。 asyncのこの「成長」は完全に自然です。非同期のベストプラクティスに関するMSDNの記事では、「async all the way」と呼ばれています。

これは、awaitが呼び出されるたびに新しいスレッドを開始しますか?

No. Awaitは、スレッドを解放していますが、スレッドを使用していません。私はどのようにasyncawaitの仕事を記述する私のブログにasync introを持っています。

1

awaitは、何かが完了するのを待っています。あなたのメソッドでタスクの結果を必要としない場合は、それを待つ必要はありません。 GetAllProductsは単にToListAsyncの結果を返す必要があります。

public static Task<List<ProductItem>> GetAllProducts() 
{ 
    var context = GetMyContext(); 
    return context.Products 
        .Select(x => new ProductItem{ //create item}) 
        .ToListAsync(); 
} 

async/awaitコンパイラは、元の同期コンテキストを格納する状態マシンを生成しなければならないため、オーバーヘッドのビットを追加し、終了した後、元の同期コンテキストを復元するために待ちタスクを待ちます。

async/awaitを、タスクの結果を処理する必要のない方法に追加するだけで、オーバーヘッドが追加されます。実際に、この問題を検出して修正するいくつかのRoslynアナライザーがあります。