Reputation: 1935
I have a very simple controller that try to read the content of a local file using await/async method. Testing it with XUnit or from a console app work like a charm. But when used from the following controller, the application gets stucked at await reader.ReadToEndAsync() and never come back.
Any idea what could be wrong! (Could it be related to some synchronization context ?)
Controller :
public ActionResult Index()
{
profiles.Add(_local.GetProfileAsync(id).Result);
return View(profiles);
}
The method GetProfileAsync looks like :
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;
}
Upvotes: 0
Views: 629
Reputation: 457057
Yes, it is a synchronization context issue. You're causing a deadlock by calling Result
instead of using await
; I explain this in detail on my blog.
In summary, await
will by default attempt to re-enter the context when it resumes the async
method. But the ASP.NET context will only allow one thread in at a time, and that thread is blocked in the call to Result
(waiting for the async
method to complete).
To fix this, use await
instead of Result
:
public async Task<ActionResult> Index()
{
profiles.Add(await _local.GetProfileAsync(id));
return View(profiles);
}
Upvotes: 3