Dave
Dave

Reputation: 1935

ASP.NET MVC controller stucked at reading a file

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

Answers (1)

Stephen Cleary
Stephen Cleary

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

Related Questions