1

約10MBのサイズのxmlファイルを返すWebサービス(Asp.net Web APIで作成)があります。

サービスはFiddlerでテストされ、機能しています

HttpClientクラスを使用してファイルをダウンロードしようとしています。await client.GetAsync()問題は、APIプロジェクトがを返したとしても、コンパイラがメソッドの外に出ることはないということHttpResponseMessageです。

これが私の機能です

public async Task<XDocument> DownloadXmlAsync(string xmlFileName)
{
    using (HttpClient client = new HttpClient())
    {
        client.BaseAddress = new Uri("http://localhost:51734/");
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml"));

        // When the copiler enters this next command, it doesn't get outside anymore
        HttpResponseMessage response = await client.GetAsync("api/applications/ApplicationXml?fileName=" + xmlFileName);
        response.EnsureSuccessStatusCode();

        string stringResponse = await response.Content.ReadAsStringAsync();

        XDocument xDoc = new XDocument(stringResponse);

        return xDoc;
    }
}

web.configのmaxRequestLengthも更新しました

<httpRuntime maxRequestLength="15360" />

私は何を間違っていますか?

編集

関数を呼び出す

public async Task<ActionResult> Index()
{
   var xmlTask = DownloadXmlAsync("1.xml");

   // doesn't reach here
   var result = xmlTask.Result;

   return View();
}
4

1 に答える 1

4

を呼び出すことで、古典的なデッドロックを引き起こしていますResultawait代わりに、次のタスクを行う必要があります。

public async Task<ActionResult> Index()
{
   var xmlTask = DownloadXmlAsync("1.xml");

   // doesn't reach here
   var result = await xmlTask;

   return View();
}

このデッドロックについてはブログで詳しく説明していますが、一般的な考え方は次のとおりです。

  • ASP.NET では、一度に 1 つのスレッドのみが要求を処理できます。
  • の場合awaitTaskコンパイラは「コンテキスト」をキャプチャし、それを使用して、Task完了時にメソッドを再開します。ASP.NET の場合、この「コンテキスト」はリクエスト コンテキストです。
  • DownloadXmlAsyncそのため、 が(非同期で) 完了するのを待つときGetAsync、未完了のタスクを に返しますIndex
  • Indexそのタスクで同期的にブロックします。これは、そのタスクが完了するまでリクエスト スレッドがブロックされることを意味します。
  • ファイルが受信されると、GetAsync完了します。ただし、DownloadXmlAsyncその「コンテキスト」を再開しようとしているため、続行できません。「コンテキスト」には、タスクでブロックされたスレッドが既に含まれています。
  • したがって、デッドロック。
于 2013-02-14T13:55:54.463 に答える