我有一个非常简单的控制器,它尝试使用await / async方法读取本地文件的内容。使用XUnit或从控制台应用程序进行测试就像魅力一样。 但是当从以下控制器中使用时,应用程序会停留在等待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;
}
答案 0 :(得分:3)
是的,这是同步上下文问题。您通过调用Result
而不是使用await
来导致死锁;我解释一下in detail on my blog。
总之,await
默认情况下会在恢复async
方法时尝试重新输入上下文。但ASP.NET上下文一次只允许一个线程,并且在调用Result
时阻止该线程(等待async
方法完成)。
要解决此问题,请使用await
代替Result
:
public async Task<ActionResult> Index()
{
profiles.Add(await _local.GetProfileAsync(id));
return View(profiles);
}