0

await/async メソッドを使用してローカル ファイルの内容を読み取ろうとする非常に単純なコントローラーがあります。XUnit またはコンソール アプリからテストするのは魅力的です。ただし、次のコントローラーから使用すると、アプリケーションは await reader.ReadToEndAsync() でスタックし、二度と戻ってきません。

何が間違っている可能性がありますか?(同期コンテキストに関連している可能性がありますか?)

コントローラー:

 public ActionResult Index()
 {
    profiles.Add(_local.GetProfileAsync(id).Result);
    return View(profiles);
 }

メソッド GetProfileAsync は次のようになります。

public override async Task<Profile> GetProfileAsync(long id)
{
    // Read profile
    var filepath = Path.Combine(_directory, id.ToString() , "profile.html");
    if (!File.Exists(filepath))
        throw new FileNotFoundException(string.Format("File not found: {0}", filepath));
    string content;
    using (var fs = new FileStream(filepath, FileMode.Open, FileAccess.Read))
    {
        using (var reader = new StreamReader(fs))
        {
            content = await reader.ReadToEndAsync();
        }
    }
 ...
    return profile;
 }
4

1 に答える 1

3

はい、同期コンテキストの問題です。;Resultを使用する代わりに呼び出してデッドロックを引き起こしています。awaitこれについては、ブログで詳しく説明しています。

要約すると、デフォルトでは、メソッドawaitを再開するときにコンテキストへの再入力を試みます。asyncただし、ASP.NET コンテキストでは、一度に 1 つのスレッドのみが許可され、そのスレッドは呼び出しでブロックされますResult(メソッドが完了するのを待機しasyncます)。

これを修正するには、await代わりにResult次を使用します。

public async Task<ActionResult> Index()
{
  profiles.Add(await _local.GetProfileAsync(id));
  return View(profiles);
}
于 2013-08-31T01:01:26.543 に答える