Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using async in ASP.Net MVC

I had the following action which hung and never returned:

public Task<ActionResult> ManageProfile(ManageProfileMessageId? message)
        {
            ViewBag.StatusMessage =
                message == ManageProfileMessageId.ChangeProfileSuccess
                    ? "Your profile has been updated."
                                : message == ManageProfileMessageId.Error
                                      ? "An error has occurred."
                                      : "";
            ViewBag.ReturnUrl = Url.Action("ManageProfile");

            var user = UserManager.FindByIdAsync(User.Identity.GetUserId());
            var profileModel = new UserProfileViewModel
            {
                Email = user.Email,
                City = user.City,
                Country = user.Country
            };

            return View(profileModel);
        }

but when I converted it to this:

 public async Task<ActionResult> ManageProfile(ManageProfileMessageId? message)
        {
            ViewBag.StatusMessage =
                message == ManageProfileMessageId.ChangeProfileSuccess
                    ? "Your profile has been updated."
                                : message == ManageProfileMessageId.Error
                                      ? "An error has occurred."
                                      : "";
            ViewBag.ReturnUrl = Url.Action("ManageProfile");

            var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
            var profileModel = new UserProfileViewModel
            {
                Email = user.Email,
                City = user.City,
                Country = user.Country
            };

            return View(profileModel);
        }

It returned right away. So Im not sure what is going on with this? If its as simple as the method returned without waiting on the result of FindByIdAsync, then why didn't I get a view with nothing in it.

So it appears to me that it neither waited for the return of:

UserManager.FindByIdAsync(User.Identity.GetUserId());

nor returned a null profile nor threw an exception. So I dont get whats happening here when it's hanging in the first example.

like image 534
rism Avatar asked Nov 25 '25 02:11

rism


1 Answers

I assume your first example was using Result, thus causing a deadlock that I explain on my blog.

In summary, ASP.NET provides a "request context" which only allows one thread in at a time. When you block a thread using Result, that thread is locked into that context. Later, when FindByIdAsync attempts to resume on that context, it cannot because there's another thread already blocked in it.

like image 55
Stephen Cleary Avatar answered Nov 26 '25 17:11

Stephen Cleary



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!