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

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;
}

Related

What is the difference between "await callingMethodAsync()" and callingMethodAsync().wait()"? [duplicate]

I don't quite understand the difference between Task.Wait and await.
I have something similar to the following functions in a ASP.NET WebAPI service:
public class TestController : ApiController
{
public static async Task<string> Foo()
{
await Task.Delay(1).ConfigureAwait(false);
return "";
}
public async static Task<string> Bar()
{
return await Foo();
}
public async static Task<string> Ros()
{
return await Bar();
}
// GET api/test
public IEnumerable<string> Get()
{
Task.WaitAll(Enumerable.Range(0, 10).Select(x => Ros()).ToArray());
return new string[] { "value1", "value2" }; // This will never execute
}
}
Where Get will deadlock.
What could cause this? Why doesn't this cause a problem when I use a blocking wait rather than await Task.Delay?
Wait and await - while similar conceptually - are actually completely different.
Wait will synchronously block until the task completes. So the current thread is literally blocked waiting for the task to complete. As a general rule, you should use "async all the way down"; that is, don't block on async code. On my blog, I go into the details of how blocking in asynchronous code causes deadlock.
await will asynchronously wait until the task completes. This means the current method is "paused" (its state is captured) and the method returns an incomplete task to its caller. Later, when the await expression completes, the remainder of the method is scheduled as a continuation.
You also mentioned a "cooperative block", by which I assume you mean a task that you're Waiting on may execute on the waiting thread. There are situations where this can happen, but it's an optimization. There are many situations where it can't happen, like if the task is for another scheduler, or if it's already started or if it's a non-code task (such as in your code example: Wait cannot execute the Delay task inline because there's no code for it).
You may find my async / await intro helpful.
Based on what I read from different sources:
An await expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.
To wait for a single task to complete, you can call its Task.Wait method. A call to the Wait method blocks the calling thread until the single class instance has completed execution. The parameterless Wait() method is used to wait unconditionally until a task completes. The task simulates work by calling the Thread.Sleep method to sleep for two seconds.
This article is also a good read.
Some important facts were not given in other answers:
async/await is more complex at CIL level and thus costs memory and CPU time.
Any task can be canceled if the waiting time is unacceptable.
In the case of async/await we do not have a handler for such a task to cancel it or monitoring it.
Using Task is more flexible than async/await.
Any sync functionality can by wrapped by async.
public async Task<ActionResult> DoAsync(long id)
{
return await Task.Run(() => { return DoSync(id); } );
}
async/await generate many problems. We do not know if await statement will be reached without runtime and context debugging. If first await is not reached, everything is blocked. Sometimes even when await seems to be reached, still everything is blocked:
https://github.com/dotnet/runtime/issues/36063
I do not see why I must live with the code duplication for sync and async method or using hacks.
Conclusion: Creating Tasks manually and controlling them is much better. Handler to Task gives more control. We can monitor Tasks and manage them:
https://github.com/lsmolinski/MonitoredQueueBackgroundWorkItem
Sorry for my english.

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!

ASP.NET MVC what threadpool is used for custom tasks?

In the book Pro ASP.NET MVC 4 there is an example of an asynchronous action:
public class RemoteDataController : AsyncController
{
public async Task<ActionResult> ConsumeAsyncMethod() {
string data = await new RemoteService().GetRemoteDataAsync();
return View("Data", (object)data);
}
}
public class RemoteService
{
public async Task<string> GetRemoteDataAsync() {
return await Task<string>.Factory.StartNew(() => {
Thread.Sleep(2000);
return "Hello from the other side of the world";
});
}
}
My question is: Would the task not just use a thread from the threadpool that is also used for serving requests?
Say I have a synchronous I/O bound method. I think calling this method with Task.Run and await in my action wouldn't lead to more requests that can be handled concurrently because the task for the I/O bound method is not available any longer for request handling. Or is there a separate threadpool only for the requests and using Task.Run in actions automatically uses a different one? What got me thinking is this question: Using ThreadPool.QueueUserWorkItem in ASP.NET in a high traffic scenario where the answer was more or less that only async methods from libraries should be used, where those libraries use their own thread pool.
Is it possible to configure the behavior? Does it work the same way with ASP.NET WebForms?
example
That's a really poor example. There are three things that I see immediately wrong with it, but the major one is as you pointed out:
Would the task not just use a thread from the threadpool that is also used for serving requests?
Yes, that example would.
Please consider this example instead:
public class RemoteDataController : Controller
{
public async Task<ActionResult> ConsumeAsyncMethod() {
string data = await new RemoteService().GetRemoteDataAsync();
return View("Data", data);
}
}
public class RemoteService
{
public async Task<string> GetRemoteDataAsync() {
await Task.Delay(2000);
return "Hello from the other side of the world";
}
}
The original example blocked a thread pool thread using Thread.Sleep. That's completely counterproductive on ASP.NET. As a general rule, do not use Task.Factory.StartNew or Task.Run on ASP.NET.
In contrast, Task.Delay is a naturally-asynchronous operation. By "naturally-asynchronous", I mean asynchronous in the same way that I/O operations are asynchronous (e.g., HttpClient for web calls). Naturally-asynchronous operations do not use threads, hence their appeal for ASP.NET servers (reducing pressure on the thread pool, allowing you to scale more).
It's interesting to think about how this works: when you use naturally-asynchronous methods as in my example, a thread starts the request up until it hits the await; at that point the request thread is returned to the thread pool (!) and for the next two seconds there are no threads processing that request (and yet the request has not completed). I like to call this phenomenon "zero-threaded concurrency". When the Delay finishes, a thread resumes processing the request and completes it.
On a side note, AsyncController is a leftover from MVC3. It is not needed with async/await.

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.

Preventing a deadlock when calling an async method without using await

I need to call a method returning a Task from within
public override void OnActionExecuting(ActionExecutingContext filterContext)
It wont let me make this method async it throws the following
An asynchronous module or handler completed while an asynchronous
operation was still pending.
and when calling
entityStorage.GetCurrentUser().Result
I get a deadlock. How can I avoid this?
I have been playing around with it coming up with stuff like
entityStorage.GetCurrentUser().Result.ConfigureAwait(false).GetAwaiter().GetResult();
But this isn't working. How can I do it? My solution will need to work with ASP.NET 4 and the Async Targetting Pack, I can't use ASP.NET 4.5 as am deploying to Azure.
The cause of the deadlock is explained here. In short, don't block on async code. You should use ConfigureAwait(false) in your library async code and await the results (not use Result or Wait).
Update: Please vote here for the MVC team to add support for async action filters.
Since await is just syntax sugar for the compiler rewriting a continuation for you, the most 'direct' path would be to take whatever code was going to follow your await and make it a ContinueWith call.
So, something like:
entityStorage.GetCurrentUser().ContinueWith(t =>
{
// do your other stuff here
});
If you MUST convert asynch to synch.
public User GetCurrentUserSynch()
{
return Task.Run(() =>
{
var asyncResult = entityStorage.GetCurrentUser();
while (!asyncResult.IsCompleted)
{
Application.Current.TryFindResource(new object()); // This is for WPF but you can do some other nonsense action of your choosing
}
return asyncResult.Result;
}).Result;
}
Otherwise use #Stephen's answer.

Resources