Asp.net Web API:HttpClient下载大文件中断

时间:2013-02-14 13:23:43

标签: asp.net web-services asp.net-web-api

我有一个Web服务(在Asp.net Web API中制作),它返回一个大小约为10MB的xml文件。

该服务已经过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();
}

1 个答案:

答案 0 :(得分:4)

通过调用Result导致经典死锁。相反,您应该await任务:

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

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

   return View();
}

I explain this deadlock in full on my blog,但总的想法是这样的:

  • ASP.NET只允许一个线程一次处理一个请求。
  • 当您await Task时,编译器将捕获“上下文”并在Task完成时使用它来恢复该方法。对于ASP.NET,此“上下文”是请求上下文。
  • 因此当DownloadXmlAsync(异步)等待GetAsync完成时,它会将未完成的任务返回给Index
  • Index同步阻止该任务。这意味着请求线程将被阻止,直到该任务完成。
  • 收到文件后,GetAsync完成。但是,DownloadXmlAsync无法继续,因为它正在尝试恢复该“上下文”,并且“上下文”中已经有一个线程:在该任务上被阻止的那个。
  • 因此,死锁。