1

我有一个 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();
}
4

1 回答 1

4

您通过调用Result. 相反,您应该await执行以下任务:

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

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

   return View();
}

我在我的博客上完整地解释了这个僵局,但总体思路是这样的:

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