ASP.NET MVC控制器在读取文件时出错

本文关键字:文件 出错 读取 NET MVC 控制器 ASP | 更新日期: 2023-09-27 18:29:52

我有一个非常简单的控制器,它尝试使用wait/async方法读取本地文件的内容。用XUnit或控制台应用程序测试它就像一个魅力。但是当从下面的控制器使用时,应用程序会被阻塞在等待读取器上。ReadToEndAsync(),然后再也不会回来。

知道可能出了什么问题吗!(这可能与某些同步上下文有关吗?)

控制器:

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

GetProfileSync方法看起来像:

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;
 }

ASP.NET MVC控制器在读取文件时出错

是的,这是一个同步上下文问题。您调用Result而不是使用await导致死锁;我在博客上详细解释了这一点。

总之,默认情况下,await在恢复async方法时将尝试重新输入上下文。但是ASP.NET上下文一次只允许一个线程进入,并且该线程在对Result的调用中被阻止(等待async方法完成)。

要解决此问题,请使用await而不是Result:

public async Task<ActionResult> Index()
{
  profiles.Add(await _local.GetProfileAsync(id));
  return View(profiles);
}