Why do you use async if you don't promote it to the controller? - asp.net-mvc

I'm trying to figure out how to use async/await in C# in my Asp.Net MVC.
The main point seems to be that it helps asp.net for releasing threads from the worker pool when you are doing IO (so they can process other stuff). For doing so you have to promote the async/await modifier from the method doing the IO call up to the controller action (you better have just a few layers).
Is there any point in using this feature without promoting the async/await up to my controller ? (by adding Task.Wait after a call to an Async method for instance).

The answer is "yes", but using Task.Wait() in an action is not a good idea because it can lead to a deadlock situation.
Consider the following from the guide, Async/Await Best Practice by Stephen Cleary:
Figure 3 A Common Deadlock Problem When Blocking on Async Code
public static class DeadlockDemo
{
private static async Task DelayAsync()
{
await Task.Delay(1000);
}
// This method causes a deadlock when called in a GUI or ASP.NET context.
public static void Test()
{
// Start the delay.
var delayTask = DelayAsync();
// Wait for the delay to complete.
delayTask.Wait();
}
}
However, if you add ConfigureAwait(false) to DelayAsync() like this:
await Task.Delay(1000).ConfigureAwait(false)
then you can avoid deadlocks, as explained in the article:
Aside from performance, ConfigureAwait has another important aspect: It can avoid deadlocks. Consider Figure 3 again; if you add “ConfigureAwait(false)” to the line of code in DelayAsync, then the deadlock is avoided. This time, when the await completes, it attempts to execute the remainder of the async method within the thread pool context. The method is able to complete, which completes its returned task, and there’s no deadlock. This technique is particularly useful if you need to gradually convert an application from synchronous to asynchronous.

Do not use Task.Wait as it can deadlock or produce an AggregateException. If you need to do this then you should use Task.WhenAll which is non-blocking.
Generally though, it is safest to use async code end-to-end. The benefit of using async away through the entire stack is that your code will be easier to debug and error handling much simpler.
So yes, if you are going to use async/await - include it in your controller and avoid using blocking code like Task.Wait.

Related

Make ActionResult Asynchronous To Increse Performance And elimate Flickering

I want to make this Action Asynchronous,Can Anyone Help On this.
[HttpGet]
public ActionResult LoadAddressDetail(int? whId)
{
try
{
return Json(new
{
GridData = wareHouseMasterService.LoadAddressGrid(GetCommonProperty(), whId ?? 0, DataManager.CustomerType, DataManager.CustomerTypeCode.WAREHOUSE.ToString()),
Status = true
}, JsonRequestBehavior.AllowGet);
}
catch (Exception e) { this.loggerService.Error(e); return Json(false, JsonRequestBehavior.AllowGet); }
}
Since I am Using Three httpget Methods executed at one page load and the screen flickers Three Times.So I need parallel Processing.
Not sure exactly what you're looking for here. Making an action async is as simple as adding the async keyword and returning Task<ActionResult>:
public async Task<ActionResult> LoadAddressDetail(int? whId)
Of course, then, you must await something. The only thing I see that seems to do any work is wareHouseMasterService.LoadAddressGrid, but you've provided no details about what this does. Generally speaking, you would need to make this method async, as well, or add an async version of it. Then, you would simple do:
GridData = await wareHouseMasterService.LoadAddressGridAsync(...),
All that said, there's a big gotcha to keep in mind. Async, in the context of a web request, isn't the same thing as parallel processing, and it also does not make anything happen "faster". Additionally, there's a minor performance impact from using async, as there's overhead that goes along with that. In other words, simply making this action action async does not really in fact serve any other your mentioned goals.
The true reason to use async is to allow your web server to handle load more efficiently. When the thread handling the request is in a wait-state, async allows the thread to be returned to the pool to field other requests. Since there's a ceiling to the amount of threads a web server can spawn, and therefore the number of requests it can handle simultaneously, async gives you some extra head room when the server is under load. That's pretty much it, though.
That said, if you're trying all this out in development, using IIS Express, it's important to realize that IIS Express is single-threaded. In other words, requests are queued and handled serially, since raw performance is not a real factor in development. Therefore, in this situation, your three AJAX requests are being processed one at a time, rather than in parallel as they likely would be in full IIS, and that may be the source of what you're experiencing. Async may help here, but not necessarily. Regardless, it's only an issue in development.
Short of all that, you need to look at your JavaScript and ensure that you are doing things in an optimized way such that the AJAX requests are processed efficiently. There's also ways to minimize the flash of unstyled content issues apart from simply making everything happen quicker. However, since you've posted no code in this regard, there's not more that can be said.

Does TransactionScope flow across async continuations without the original context?

I'm developing an ASP.NET MVC5 application and I have the following situation:
Async controller method calls custom async method 1+ times, each Task object being stored successively in a List
Each custom async method call establishes its own top-level TransactionScope with TransactionScopeAsyncFlow.Enabled
Each custom async method call performs transactional work, then awaits DbContext.SaveChangesAsync()
While this is occurring, the controller method performs its own transactional work within its own unrelated TransactionScope, then awaits Task.WhenAll()
The question arises from using ConfigureAwait(false) when awaiting DbContext.SaveChangesAsync(). Each call to the custom async method starts in the controller method's ASP.NET request context but I don't see any need to recapture it when SaveChangesAsync() returns EXCEPT if it's going to mess up the current transaction. This is important because if an unrecoverable exception occurs in the controller method before I await Task.WhenAll, I need to cancel the async Tasks within a catch block, which means instead of awaiting Task.WhenAll() I'm forced to use the blocking method Task.WaitAll(), which I'm pretty sure will deadlock if the async Tasks are trying to recapture the original request context.
Sorry if this is a repeat question. I did quite a bit of searching and couldn't get a clear answer. Feel free to tell me this is bad programming or whatever, just at least suggest an alternative and leave my mom out of it. Thanks!

Does let!/do! always run the async object in a new thread?

From the wikibook on F# there is a small section where it says:
What does let! do?#
let! runs an async<'a> object on its own thread, then it immediately
releases the current thread back to the threadpool. When let! returns,
execution of the workflow will continue on the new thread, which may
or may not be the same thread that the workflow started out on.
I have not found anywhere else in books or on the web where this fact (highlighted in bold) is stated.
Is this true for all let!/do! regardless of what the async object contains (e.g. Thread.Sleep()) and how it is started (e.g. Async.Start)?
Looking in the F# source code on github, I wasn't able to find the place where a call to bind executes on a new (TP) thread. Where in the code is the magic happening?
Which part of that statement do you find surprising? That parts of a single async can execute on different threadpool threads, or that a threadpool thread is necessarily being released and obtained on each bind?
If it's the latter, then I agree - it sounds wrong. Looking at the code, there are only a few places where a new work item is being queued on the threadpool (namely, the few Async module functions that use queueAsync internally), and Async.SwitchToNewThread spawns a non-threadpool thread and runs the continuation there. A bind alone doesn't seem to be enough to switch threads.
The spirit of the statement however seems to be about the former - no guarantees are made that parts of an async block will run on the same thread. The exact thread that you run on should be treated as an implementation detail, and when you yield control and await some result, you can be pretty sure that you'll land on a different thread at least some of the time.
No. An async operations might execute synchronously on the current thread, or it might wind up completing on a different thread. It depends entirely on how the async API in question is implemented.
See Do the new C# 5.0 'async' and 'await' keywords use multiple cores? for a decent explanation. The implementation details of F# and C# async are different, but the overall principles are the same.
The builder that implements the F# async computation expression is here.

How to set ViewBag for _Layout in MVC4 using async in every action

The usecase is simple. Info for logged in user is displayed in _Layout.cshtml. That info needs to be refreshed every time.
I found two ways to do that
Have BaseController and in its OnActionExecuting method set ViewBag.UserInfo = ...; which is later used in _Layout.cshtml
In _Layout.cshtml do #{Html.RenderAction("GlobalUserInfo", "UserInfo");}
The problem is that these two ways fail miserably with deadlocks or exceptions if UserInfo is returned from an async public async Task<UserInfo>GetUserInfo(){...} method.
So the question is this: How to set ViewBag properties on every action when data is retrieved using async/await.
MVC is not quite fully async-friendly, particularly with filters.
You could write your own RenderAsyncAction extension method or duplicate the code in all your async actions.
Alternatively, you could attempt a bit of a hack. I describe on my blog why using Result in ASP.NET can deadlock, but there's a workaround: use ConfigureAwait(false) on every await in GetUserInfo.
Then you can define a synchronous wrapper:
public UserInfo GetUserInfoBlocking()
{
return GetUserInfo().Result;
}
You should be able to use GetUserInfoBlocking in OnActionExecuting or RenderAction.
Please note the side effects:
This approach uses multiple threads per request, so this will decrease scalability. The pure async approach uses multiple requests per thread, so it increases scalability.
Any exceptions from GetUserInfo will be wrapped in an AggregateException, so be sure your logging will capture the InnerException details or you'll get meaningless errors in your logs.
It's definitely best to use async all the way down instead of blocking like this. But sometimes MVC doesn't leave you a choice (hopefully this will change in the future).

ASP.NET MVC 4 async child action

I have an ASP.NET MVC 4 application targeting .NET 4.5. One of our child actions makes a call out to a web service using HttpClient.
Since we're blocking on IO waiting for the HttpClient response, it makes a great deal of sense to convert the code to the async/await pattern. However, when MVC 4 attempts to execute the child action, we get the following error message:
HttpServerUtility.Execute blocked while waiting for an asynchronous operation to complete.
At first glance, it appears as though MVC 4 does not support async/await within a child action. The only remaining option is to run using synchronous code and force a "Wait" on the async task.
As we all know, touching .Result or .Wait() on an async task in an ASP.NET context will cause an immediate deadlock. My async logic is wrapped in a class library, so I can't use the "await blah.ConfigureAwait(false)" trick. Remember, tagging "async" on the child action and using await causes an error, and that prevents me from configuring the await.
I'm painted into a corner at this point. Is there any way to consume async methods in an MVC 4 child action? Seems like a flat out bug with no workarounds.
There are still parts of MVC that aren't async-friendly; I hope these will be addressed in the future. Please do create a Connect or UserVoice issue for this.
My async logic is wrapped in a class library, so I can't use the "await blah.ConfigureAwait(false)" trick.
You probably should add ConfigureAwait(false) to the calls in your class library (if you can).
You could also hack up an alternate solution. If your class library method doesn't need the ASP.NET context, then you could have a thread pool thread do the (a)waiting for you:
try
{
var result = Task.Run(async () => { await MyHttpRequest(...); }).Result;
}
catch (AggregateException ex) { ... }
The effect is similar to ConfigureAwait(false): since MyHttpRequest runs in a thread pool context, it will not attempt to enter the ASP.NET context when it completes.
The format of Stephen's answer didn't quite work for me (maybe it's an async noob problem, but hey).
I had to do write the async expression in this format to get a strongly typed return value.
Person myPerson = Task.Run(() => asyncMethodWhichGetsPerson(id)).Result;

Resources