2016-10-18 9 views
11

Stephen Clearyが非同期コードでブロックすることについては、すべてthe famous blog postを知っています。 Home/Indexを要求するときにMVC 5では、次のコードのデッドロック:MVCコアで非同期コードをブロックすることはできますか?

public class HomeController : Controller 
{ 
    public string Index() 
    { 
     var model = AsyncMethod(); 
     return model.Result; 
    } 

    private async Task<string> AsyncMethod() 
    { 
     await Task.Run(() => Thread.Sleep(2000)); 
     return "Hello"; 
    } 
} 

しかし、まったく同じコードは、MVCコアWebアプリケーションでデッドロックしません。応答はHelloを返します。どうして? MVC Coreでは、1つのリクエストコンテキスト内で複数のスレッドを同時に実行できますか? 非同期コードでブロックしないでくださいというフレーズがMVCコアで開発中ですか?

答えて

9

なぜですか?

ASP.NETコアは、上から下に向かってasyncであり、最大のスピードを実現するように設計されています。

再設計の一環として、ASP.NETチームはAspNetSynchronizationContext全体を完全に削除することができました。 ASP.NETリクエストコンテキストのいくつかの側面はコア.NETに移され、他は削除されました(例えば、HttpContext.Current)。

MVCコアでは、1つのリクエストコンテキスト内で複数のスレッドを同時に実行できますか?

いいえ「要求コンテキスト」の概念は、もはや同期コンテキストでは表現されません。

MVCコアで開発する場合、非同期コードフレーズは古いものではありませんか?

いいえ、ASP.NET Coreではデッドロックは発生しませんが、それでもやってはいけません。

"MVCコアで非同期コードをブロックできますか?"はい。 "MVCコアで非同期コードをブロックすべきですか?"いいえ

+0

ありがとうございます!私はもう一度平和的にコードすることができます:-) – Kapol

2

このコード

await Task.Run(() => Thread.Sleep(2000)); 

は偉大なパターンではないかもしれませんが、それはスティーブンの記事が参照する同じ意味で「ブロッキング」ではないです。 Wait()または.Resultにブロック

private string BlockingAsyncMethod() 
{ 
    Task.Run(() => Thread.Sleep(2000)).Wait(); 
    return "Hello"; 
} 

が、それはまだMVCコアの正しいアドバイス私の知る限りMVC 5用の無大したです:リンゴにリンゴを比較するには、あなたがこれを行う必要があるだろう。

+0

あなたの例は、MVCコアでデッドロックしません。私はまだ "Hello"を取得します – Kapol

+0

@Kapol block!= deadlock。ブロッキングとは、操作の結果を同期的に待つことを指します。デッドロックは、非同期操作で同期的に(たとえばWait()などで)ブロックすると発生することがあります。悪いパターン(非同期で同期)であっても、デッドロックは常に発生しないことに注意することが重要です**。 –

+0

申し訳ありませんが、ネイトはもちろん、デッドロックを意味していました。私の理解では、MVC 5ではデッドロックが発生していましたが、MVC Coreではこの動作を少なくとも1回は再現できません。 – Kapol

関連する問題