Using "async" (even if it should complete) as part of a MVC route deadlocks the route; how can this be avoided? - asp.net

Consider the following (based on the default MVC template), which is a simplified version of some "stuff" that happens in the background - it completes fine, and shows the expected result, 20:
public ActionResult Index()
{
var task = SlowDouble(10);
string result;
if (task.Wait(2000))
{
result = task.Result.ToString();
}
else
{
result = "timeout";
}
ViewBag.Message = result;
return View();
}
internal static Task<long> SlowDouble(long val)
{
TaskCompletionSource<long> result = new TaskCompletionSource<long>();
ThreadPool.QueueUserWorkItem(delegate
{
Thread.Sleep(50);
result.SetResult(val * 2);
});
return result.Task;
}
However, now if we add some async into the mix:
public static async Task<long> IndirectSlowDouble(long val)
{
long result = await SlowDouble(val);
return result;
}
and change the first line in the route to:
var task = IndirectSlowDouble(10);
then it does not work; it times out instead. If we add breakpoints, the return result; in the async method only happens after the route has already completed - basically, it looks like the system is unwilling to use any thread to resume the async operation until after the request has finished. Worse: if we had used .Wait() (or accessed .Result), then it will totally deadlock.
So: what is with that? The obvious workaround is "don't involve async", but that is not easy when consuming libraries etc. Ultimately, there is no functional difference between SlowDouble and IndirectSlowDouble (although there is obvious a structural difference).
Note: the exact same thing in a console / winform / etc will work fine.

It's to do with the way the synchronization context is implemented in ASP.NET (Pre .NET 4.5). There's tons of questions about this behavior:
Task.WaitAll hanging with multiple awaitable tasks in ASP.NET
Asp.net SynchronizationContext locks HttpApplication for async continuations?
In ASP.NET 4.5, there's a new implementation of the sync context that's described in this article.
http://blogs.msdn.com/b/webdev/archive/2012/11/19/all-about-httpruntime-targetframework.aspx

When you use .Result there is always a possibility of deadlock because .Result is blocking by nature. The way to avoid deadlocks is to not block on Tasks (you should use async and await all the way down). The subject is in details described here:
Don't Block on Async Code
One fix is to add ConfigureAwait:
public static async Task<long> IndirectSlowDouble(long val)
{
long result = await SlowDouble(val).ConfigureAwait(false);
return result;
}

Another fix is to use async/await throughout:
public async Task<ActionResult> Index()
{
var task = IndirectSlowDouble(10);
long result = await task;
ViewBag.Message = result.ToString();
return View();
}

Related

Blazor InvokeAsync vs await InvokeAsync

Edit: for clarification, this is in a Blazor Server application
I'm confused about the correct usage of InvokeAsync and updating the UI. The documentation has several usages without really explaining the reason for awaiting or not awaiting. I have also seen some contradictory threads without much to backup their reasoning.
It seems wrong to make all methods async to await InvokeAsync(StateHasChanged) and I read somewhere that the reason InvokeAsync was introduced was to prevent the need for async code everywhere. But then what situations might I want to await it?
awaiting:
https://learn.microsoft.com/en-us/aspnet/core/blazor/components/?view=aspnetcore-5.0&viewFallbackFrom=aspnetcore-3.0#invoke-component-methods-externally-to-update-state
non-await discard:
https://learn.microsoft.com/en-us/aspnet/core/blazor/components/rendering?view=aspnetcore-5.0
Here are some examples of different usages that I have seen, if anyone could explain or share any links with information on some of the differences between them that'd be great (thanks!)
public void IncrementCounter()
{
_counter++;
InvokeAsync(StateHasChanged);
}
public void IncrementCounter()
{
InvokeAsync(() =>
{
_counter++;
StateHasChanged);
}
}
public async Task IncrementCounter()
{
_counter++;
await InvokeAsync(StateHasChanged);
}
public async Task IncrementCounter()
{
await InvokeAsync(() =>
{
_counter++;
StateHasChanged();
});
}
IncrementCounter (a ButtonClick handler) is the wrong thing to look at - it always runs on the SyncContext thread and can always use a plain StateHasChanged() without Invoke.
So lets look at a Timer event instead. The Threading.Timer class does not support async handlers so you run in a void Tick() { ... } on an unspecified thread.
You do need InvokeAsync(StateHasChanged) here. You could make the Tick method an async void just to await the InvokeAsync but that gives of the wrong signals. Using InvokeAsync without await is the lesser evil.
void Tick() // possibly threaded event handler
{
_counter++;
InvokeAsync(StateHasChanged); // fire-and-forget mode
}
But when you are in an async method and still need InvokeAsync, it is neater to await it, just because you can.
async Task SomeService()
{
_counter++;
await InvokeAsync(StateHasChanged);
}

Entity framework 6 async/await fail in parallel request

I'm working in ASP.NET 4.6 with EF 6 to a new Web Api 2 project, I've read a lot of articles that describes the async/await pattern and It's clear that for a lot of requests this pattern increase performance for a lot of reasons.
So I decided to use it for the first time.
In decided to create a Biz project and a DAL project here an example.
This is controller method:
[HttpGet]
public async Task<bool> CheckValueValidity(string value, string type)
{
return await _accountsBiz.CheckValueTypeValidity(value, type);
}
I instance biz object in controller constructor.
This is the BIZ:
public async Task<bool> CheckValueTypeValidity(string value, string type)
{
bool isValid = false;
switch (type.ToLower())
{
case "email":
isValid = await _accountsRepository.CheckEmailValidity(value);
break;
case "username":
isValid = await _accountsRepository.CheckUserNameValidity(value);
break;
}
return isValid;
}
I instance the repository in the BIZ constructor.
Finally this is the DAL method:
public async Task<bool> CheckEmailValidity(string email)
{
using(MyEntities db = new MyEntities())
{
return await db.AspNetUsers.CountAsync(u => u.Email == email) > 0 ? false : true;
}
}
And all it seems to work perfectly until I made two request at same time, one of these return the correct value the other say
A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe.
I made the requests from two different client so the context should be different. should....
I don't know how to fix it. I read a lot and my code seems to be correct.
The question is WHY throw this error? I can't understand
Thanks for help in advice.
Ok found the error in the execution flow there is a method that use DbContext without using block.... My mistake but now it's clear that context must be disposed each request!

Web API Service - How to use "HttpContext.Current" inside async task

I'm using a "Post" async method of webApi rest service:
public async Task<object> Post([FromBody]string data)
{
object response = ExecuteServerLogics(data);
return response;
}
This above code worked good but in some of the client's calls, we experienced performance issues.
After reading some articles here, i've noticed that our webApi rest service,
is not really working asynchronously with its incoming web requests,
because we forgot to use async/await pattern :
public async Task<object> Post([FromBody]string data)
{
object response = await Task<object>.Run( () =>
{
return ExecuteServerLogics(data);
});
return response;
}
After this fix we noticed the performance got better,
but we found another critic problem:
when accessing HttpContext.Current - it returns Null reference:
public async Task<object> Post([FromBody]string data)
{
object response = await Task<object>.Run( () =>
{
var currentContext = HttpContext.Current; // Returns Null!
return ExecuteServerLogics(data);
});
return response;
}
We tried to found a solution for it, and in most posts we found that we should pass the
worker thread's HttpContext reference into the inner Task that executes the server logics.
The problem with this solution is that the server's logics methods, use many static classes that use
"HttpContext.Current" such as -
Loggers calls.
static security classes that retrieves the user.identity
static security classes that retrives the incoming request's session data, etc.
Therefore, passing the "HttpContext.Current" reference of the worker thread won't solve it.
When we tried the next solution:
public async Task<object> Post([FromBody]string data)
{
// Save worker context:
var currentContext = HttpContext.Current;
object response = await Task<object>.Run( () =>
{
// Set the context of the current task :
HttpContext.Current = currentContext ; // Causes the calls not to work asynchronously for some reason!
// Executes logics for current request:
return ExecuteServerLogics(data);
});
return response;
}
for some reason, we noticed the performance got worse again, like it had returned working synchronously again.
Our problems are:
1. Why in the last example, setting the "HttpContext.Current" inside the await task,
causes the requests to return the same bad performance results which similar to the synchronous results?
2. Is there another way we can use "HttpContext.Current" inside the inner task that call - "ExecuteServerLogics",
and in all the static classes which also call "HttpContext.Current"?
am I doing the entire design wrong somehow?
Thanks!
From the beginning:
public async Task<object> Post([FromBody]string data)
{
object response = ExecuteServerLogics(data);
return response;
}
Don't ignore compiler warnings; the compiler will generate a warning for this method that specifically states it will run synchronously.
Moving on:
in some of the client's calls, we experienced performance issues.
Asynchronous code on the server will not be faster for a single call in isolation. It only helps you scale your server.
In particular, Task.Run will negate all the performance benefits of async and then degrade performance a bit beyond that. I believe the improvement in performance that you measured was coincidental.
in most posts we found that we should pass the worker thread's HttpContext reference into the inner Task that executes the server logics.
Those posts are wrong. IMHO. You end up using the HttpContext object from a background thread, when that object is specifically designed to be only accessed from a request thread.
am I doing the entire design wrong somehow?
I do recommend you take a step back and think about the big picture. When a request comes in, it has a certain amount of work to do. Whether that work is done synchronously or asynchronously is immaterial to the client; both approaches will take about the same amount of time.
If you need to return early to the client, then you'll need a completely different architecture. The usual approach is to queue the work to a reliable queue (e.g., Azure queue), have a separate backend (e.g., Azure WebRole), and proactively notify the client when the work is completed (e.g., SignalR).
That's not to say that async is useless, though. If ExecuteServerLogics is an I/O bound method, then it should be made asynchronous rather than blocking, and then you can use asynchronous methods as such:
public async Task<object> Post([FromBody]string data)
{
object response = await ExecuteServerLogicsAsync(data);
return response;
}
This will enable your server to be more responsive and scalable overall (i.e., not get overwhelmed by many requests).
If your task is inside your ApiController-derived class, you can use:
var ctx = this.Request.Properties["MS_HttpContext"] as System.Web.HttpContextWrapper;
This will give you an HttpContext wrapper with all the usual properties.
Amir I think you're looking for something like this below. I've been dealing with the same issue, trying to optimize a series of calls. It needs to be async all the way through, which means your ExecuteServerLogics() would need to be async, and you'd have to mark the containing lamda as async as well.
I believe following that pattern you can probably eliminate most of your performance issues. Nice passing the context through like that.
public async Task<object> Post([FromBody]string data)
{
// Save worker context:
var currentContext = HttpContext.Current;
object response = await Task<object>.Run(async () =>
{
// Set the context of the current task :
HttpContext.Current = currentContext ;
// Executes logics for current request:
return await ExecuteServerLogics(data);
});
return response;
}

Can I return a Task directly with HttpResponseMessage, such no async declaration is needed

I have the following WebAPI action and is wondering if returning Task<bool> and return _store.ContainerExistsAsync(container) directly is better;
I ask because, if I understand async/await correctly, the compiler creates a statemachine at the await to return to the same state. Returning the task directly without having to await it in the action, would that be theoretical faster?
public async Task<HttpResponseMessage> GetContainer(string container)
{
if (container.Length < 3 ||
container.Length > 63 ||
!Regex.IsMatch(container, #"^[a-z0-9]+(-[a-z0-9]+)*$"))
return Request.CreateResponse(HttpStatusCode.BadRequest, new { errors = new string[1] { "Container Name is not alowed." } })
return Request.CreateResponse<bool>(HttpStatusCode.OK, await _store.ContainerExistsAsync(container));
}
Yes, if you can implement an asynchronous method without async and await, then go ahead; async/await will add overhead.
This is commonly seen when the last line of a method has the only await and looks like return await ...;
In your particular example, I'm not 100% sure whether this would work since the method is doing something after the await.
It's easy enough to make it return the Task<bool> from ContainerExistsAsync directly, but the error handling would also need to change. If throwing a HttpResponseException works well enough, then yes, you would be able to implement an asynchronous method without using async.

WinRT ViewModel DataBind to async method

I am deserializing a list of objects from an XML file, and would like to bind to the actual content of those objects in my View, passing over a ViewModel. The problem is that file operations are async and this bubbles all the way up to the ViewModel, where Property getters cannot be marked as such...
Problem
I deserialize all XML files in a folder to Profile objects and store them in a List<Profile>. This method (has to be) marked async.
public static async Task<List<Profile>> GetAllProfiles()
{
DataContractSerializer ser = new DataContractSerializer(typeof(Profile));
StorageFolder folder = await ApplicationData.Current.RoamingFolder.CreateFolderAsync("Profiles", CreationCollisionOption.OpenIfExists);
List<Profile> profiles = new List<Profile>();
foreach (var f in await folder.GetFilesAsync())
{
var fs = await f.OpenStreamForReadAsync();
profiles.Add((Profile)ser.ReadObject(fs));
fs.Dispose();
}
return profiles;
}
Ideal solution 1
The binding property in my ViewModel would then ideally call that static method like this
public async Task<ObservableCollection<string>> Lists
{
get
{
return new ObservableCollection<string>(GetAllProfiles().Select(p => p.Name));
}
}
BUT Properties cannot be marked async
Ideal solution 2
public ObservableCollection<string> Lists
{
get
{
return new ObservableCollection<string>((GetAllProfiles().Result).Select(p => p.Name));
}
}
BUT this never executes (it blocks in the await folder.GetFilesAsync() call for some reason)
Current solution
Calls an async Initialize() method that loads the result of the GetProfiles() function in a variable, and then makes a NotifyPropertyChanged("Lists") call:
public ViewModel()
{
Initialize();
}
public async void Initialize()
{
_profiles = await Profile.GetAllProfiles();
NotifyPropertyChanged("Lists");
}
private List<Profile> _profiles;
public ObservableCollection<string> Lists
{
get
{
if (_profiles != null)
return new ObservableCollection<string>(_profiles.Select(p => p.Name));
else
return null;
}
}
Question
Is there a better way?
Is there a pattern/method that I haven't yet discovered?
Edit
The root of the problem appears when doing non-UI code, and you cannot rely on the NotifyPropertyChanged to do some thread-synchronization stuff. -- The method Initialize has to be awaited and ctors cannot be async, so essentialy this is pattern is useless.
public MyClass()
{
Initialize();
}
public async void Initialize()
{
_profiles = await Profile.GetAllProfiles();
}
private ObservableCollection<Profile> _profiles;
public ObservableCollection<string> Lists
{
get
{
return _profiles; // this will always be null
}
}
Properties can't be async so this solution will not work as you mentioned. Task.Result waits for the task to complete, but this is blocking your UI thread where the I/O operation's async callback returns, so you are deadlocking your application, since the callback is never called. Your solution really is the best way. It could be improved though.
You should make the _profiles field an ObservableCollection, so you would not need to convert the List to the OC every time the list is accessed.
Since you are performing an I/O operation that can take arbitrary amount of time - you should enable some sort of a progress indicator while it is in progress.
In some cases you might want the Lists property to be lazier and only call the Init method the first time it is accessed.

Resources