Is there any danger in using ConfigureAwait(false) in WebApi or MVC controllers?

17,801

Solution 1

it seems like I should use ConfigureAwait(false) on ALL of my async calls that are not tied directly to the UI.

Not quite. That guideline doesn't make sense here, since there is no UI thread.

The parameter passed to ConfigureAwait is continueOnCapturedContext, which explains more clearly the scenario. You want to use ConfigureAwait(false) whenever the rest of that async method does not depend on the current context.

In ASP.NET 4.x, the "context" is the request context, which includes things like HttpContext.Current and culture. Also - and this is the undocumented part - a lot of the ASP.NET helper methods do depend on the request context.

(Side note: ASP.NET Core no longer has a "context")

should I be using .ConfigureAwait(false) on all of the above await calls?

I haven't heard any firm guidance on this, but I suspect it's OK.

In my own code, I never use ConfigureAwait(false) in my controller action methods, so that they complete already within the request context. It just seems more right to me.

Solution 2

If there's no actual context in a ASP.NET Core application, it should do no harm nor good to add .ConfigureAwait(false) to your awaitable methods into controllers.

However, if there is a chance that eventually in the future, for whatever reason, there's something like a context to be taken into account as in ASP.NET 4, that would be a different story. We could not risk running in a different context, unless we don't give a damn about it (in which case we could use whatever thread is available for processing, thus possibly improving performance).

My choice here is to add ConfigureAwait(false) even if it's not used.

Share:
17,801
SB2055
Author by

SB2055

Updated on June 07, 2022

Comments

  • SB2055
    SB2055 almost 2 years

    Say I have two scenarios:

    1) WebApi Controller

        [System.Web.Http.HttpPost]
        [System.Web.Http.AllowAnonymous]
        [Route("api/registerMobile")]
        public async Task<HttpResponseMessage> RegisterMobile(RegisterModel model)
        {
            var registerResponse = await AuthUtilities.RegisterUserAsync(model, _userService, User);
            if (registerResponse.Success) {
                var response = await _userService.GetAuthViewModelAsync(model.Username, User);
                return Request.CreateResponse(HttpStatusCode.OK, new ApiResponseDto() { Success = true, Data = response });
            }
            else {
                return Request.CreateResponse(HttpStatusCode.OK, registerResponse);
            }
    
        }
    

    2) MVC Controller

        [Route("public")]
        public async Task<ActionResult> Public()
        {
            if (User.Identity.IsAuthenticated)
            {
                var model = await _userService.GetAuthViewModelAsync(User.Identity.Name);
                return View("~/Views/Home/Index.cshtml", model);
            }
            else
            {
                var model = await _userService.GetAuthViewModelAsync(null);
                return View("~/Views/Home/Index.cshtml", model);
            }
        }
    

    I've been reading up on when I should use ConfigureAwait and it seems like I should use ConfigureAwait(false) on ALL of my async calls that are not tied directly to the UI. I don't know what that means though... should I be using .ConfigureAwait(false) on all of the above await calls?

    I'm looking for some unambiguous guidelines around when exactly I should be using it.

    This question is NOT the same as the Best practice to call ConfigureAwait for all server-side code - I am looking for a straightforward answer on the use-case for this method in the context of WebApi and MVC, not as general C#.

  • David Clarke
    David Clarke about 6 years
    Any update on this Stephen? I'm writing controller code in asp.net core mvc and wondering what the implications are of using/not using ConfigureAwait(false). Your side note doesn't really help - if ASP.NET Core has no context, does that mean I should use ConfigureAwait(false)?
  • Stephen Cleary
    Stephen Cleary about 6 years
    @DavidClarke: Since there's no context, ConfigureAwait(false) has no effect. More info: blog.stephencleary.com/2017/03/…
  • David Clarke
    David Clarke about 6 years
    @StephenCleary thanks, that was an exceptionally helpful reference
  • Landerah
    Landerah over 5 years
    Is there a way to find which ASP.NET methods rely on the context?
  • Stephen Cleary
    Stephen Cleary over 5 years
    @Landerah: Not to my knowledge. Even if you could, it would be an implementation detail that can change with the next version. And it doesn't really matter much at this point anyway, since ASP.NET Core is the future.
  • Shishir Gupta
    Shishir Gupta about 5 years
    ConfigureAwait(false) does not disable asynchronous await! It simply means use whatever context is available to resume execution when the said async method completes
  • rboy
    rboy about 3 years
    @StephenCleary is there a context, HttpContext.Current.Response, in .NET Framework 4.7.2 WebAPI2 that we need to worry about when using ConfigureAwait(false)?
  • Stephen Cleary
    Stephen Cleary about 3 years
    @rboy: Yes. HttpContext.Current is part of the context.
  • kuldeep
    kuldeep over 2 years
    @StephenCleary this usually means that we are OK to NOT await this async method, and it is fine that this async method is fire and forget?
  • Stephen Cleary
    Stephen Cleary over 2 years
    @kuldeep: There's nothing in this question or answer that has anything to do with fire-and-forget.
  • kuldeep
    kuldeep over 2 years
    @StephenCleary sorry for confusion, but i have noticed sometimes use of ConfigureAwait without await keyword and sometimes with await keyword. So if we are using it in a method that has no Task<T> or Task being returned, is this ok to use ConfigureAwait(false) without await keyword?
  • Stephen Cleary
    Stephen Cleary over 2 years
    @kuldeep: ConfigureAwait configures the await. If there's no await, then it doesn't do anything.
  • kuldeep
    kuldeep over 2 years
    Thanks for your reply, so if there is no await then it is treated as synchronous (blocking) call ?
  • Stephen Cleary
    Stephen Cleary over 2 years
    @kuldeep: No; it would be fire-and-forget, which is almost never what you want. Feel free to ask your own question if you want more information.