Consider the following ASP.NET Web API Delegating Handler:
public class MyHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
var guid = Guid.NewGuid();
HttpContext.Current.Items["foo"] = guid;
// An Async operation
var result = await base.SendAsync(request, cancellationToken);
//All code from this point is not gauranteed to run on the same thread that started the handler
var restoredGuid = (Guid)HttpContext.Current.Items["foo"];
//Is this gauranteed to be true
var areTheSame = guid == restoredGuid;
return result;
}
}
The above example is in a delegating handler, the same problem I am trying to fix applies in Controllers, Business Objects, etc.
I am ultimately trying to provide some simple in-memory shared state between various objects per HTTP Request
As I understand it during Async operations the ASP.NET thread originally running the operation is returned to the thread pool and a different thread may be used to finish the request after the Async operation has completed.
Does this affect the HttpContext.Current.Items collection?
Is an item that was in the Items collection guaranteed to be there when the Request resumes?
I'm aware that using HttpContext.Current is often frowned upon by
the wider community these days for reasons I completely agree
with... I'm just helping someone out of a jam.
Storing this data in the Request.Items collection is not suitable to solve this problem as my colleague requires a static due to some poor design decisions.
Many Thanks
As I understand it during Async operations the ASP.NET thread originally running the operation is returned to the thread pool and a different thread may be used to finish the request after the Async operation has completed.
That is correct. But let's talk about async on ASP.NET for just a minute.
async requires .NET 4.5. Furthermore, ASP.NET 4.5 introduces a "quirks mode" on the server side, and you have to turn the SynchronizationContext quirk off. You can do this by either setting httpRuntime.targetFramework to 4.5 or using an appSettings with aspnet:UseTaskFriendlySynchronizationContext value of true.
If your web.config does not have one of those entries, then the behavior of async is undefined. See this post for more details. I recommend using the targetFramework setting and fixing any problems that come up.
Does this affect the HttpContext.Current.Items collection? Is an item that was in the Items collection guaranteed to be there when the Request resumes?
The AspNetSynchronizationContext preserves the current request context across await points. This includes HttpContext.Current (which includes Items, User, etc).
Another possibility is CallContext.Logical[Get|Set]Data, which also flows across await points. This is useful if you don't want a code dependency on HttpContext, but has slightly more overhead.
I gave a talk at ThatConference a couple weeks ago on async on the server side; you may find the slides helpful, particularly the ones dealing with Context and Thread-Local State.
Cutting a long story short, it normally should. Unless you are using ConfigureAwait(false) which can have a side effect with continuation not flowing the context.
Alternatively try adding this setting in your app.
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
UPDATE
NOTE!!
Initially I put false. But it must be true so that context flows.
Related
Context
I've got .NET Framework 4.6.1 WebApi application. This application calls various web services. Therefore I've made an implementation of IClientMessageInspector in order to do some logging
of WCF (SOAP) requests/replies.
Issue
However after some time I've realized that some replies are logged under a different principal, i.e. principal A makes a request and receives a reply and yet the response is logged under principal B.
Below is a simplified minimalistic example of the implementation just to demonstrate the issue.
public class MyClientMessageInspector : IClientMessageInspector
{
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
var correlationState = new CorrelationState
{
Guid = Guid.NewGuid()
};
// Principal A
Debug.WriteLine(Thread.CurrentPrincipal);
// Guid: 2abf9a7b-dac2-4c0d-b38d-1cdfb95405a7
Debug.WriteLine(correlationState.Guid);
return correlationState;
}
public void AfterReceiveReply(ref Message reply, object correlationStateObject)
{
var correlationState = (CorrelationState) correlationStateObject;
// Principal B - How come???
Debug.WriteLine(Thread.CurrentPrincipal);
// Guid: 2abf9a7b-dac2-4c0d-b38d-1cdfb95405a7 (matches Guid from request)
Debug.WriteLine(correlationState.Guid);
}
}
Both Thread.CurrentPrincipal and HttpContext.CurrentUser are only set in the Global.asax.cs in the Application_PostAuthenticateRequest event.
The application heavily utilizes async/await paradigm and almost every async call (including calls of the web services) is followed by .ConfigureAwait(false). However my understanding is that Thread.CurrentPrincipal is flowed between threads reagardless of the usage of ConfigureAwait(false). That seems to be true since all my other logs are made under a correct principal, even those that happen after AfterReceiveReply.
Question
Is there an explanation why Thread.CurrentPrincipal in AfterReceiveReply contains a different principal? I know how to workaround this issue - I could send the principal between BeforeSendRequest and AfterReceiveReply within the CorrelationState object. But before doing so I need to understand why my code behaves differently than expected and also if there is possibly a better solution than the workaround.
When you use .ConfigureAwait(false) on an application with a threadpool any of the threads in the pool might be chosen to continue execution. Some of those threads might have the same context as your originating thread, others might have different contexts. You have no control over what thread takes over once you use .ConfigureAwait(false).
There is a more detailed description of what's going on here: https://medium.com/rubrikkgroup/understanding-async-avoiding-deadlocks-e41f8f2c6f5d
The above article talks about using .Result and Task.Run, not .ConfigureAwait(false) however .ConfigureAwait(false) effectively does this behind the scenes anyway if you ever call a .wait() or .result on the call anywhere in your call stack. Importantly this only happens if your code is actually waiting for something. If your async methods happen to have the data they need to continue they will happily stay on their original thread and the context variables will match.
Also when running Async with .ConfigureAwait(false) you can be sent from your first thread to another thread, then back to your first thread if it's free and the code needed to wait for something like a network read. The threadpool means you have a limited number of threads that can be called on and most operations that involve threads don't actually spin up a completely new one.
Some further reading that might help:
https://devblogs.microsoft.com/dotnet/configureawait-faq/
I've scoured the SO for answers but found none that pertain to the problem at hand, although this one nails it on "why", but isn't solving it.
I have a REST endpoint that needs to gather data from other endpoints - in doing so, it accesses the HttpContext (setting authentication, headers, etc... all done with 3rd party lib I don't have access to).
Unfortunately, this library for service communication is made to be synchronous, and we want to parallelize its use.
In the following example (abstracted) code, the issue is that CallEndpointSynchronously unfortunately uses some built in authentication, which throws null exception when HttpContext isn't set:
public class MyController: ApiController
//...
[HttpPost]
public async Task<IHttpActionResult> DoIt(IEnumerable<int> inputs)
{
var tasks = inputs.Select(i =>
Task.Run(()=>
{
/* call some REST endpoints, pass some arguments, get the response from each.
The obvious answer (HttpContext.Current = parentContext) can't work because
there's some async code underneath (for whatever reasons), and that would cause it
to sometimes not return to the same thread, and basically abandon the Context,
again resulting in null */
var results = Some3rdPartyTool.CallEndpointSynchronously(MyRestEndpointConfig[i]);
return results;
});
var outcome = await Task.WhenAll(tasks);
// collect outcome, do something with it, render outputs...
}
Is there a cure for this?
We want to optimize for single requests, not interested in maximizing parallel users at this moment.
Unfortunately, this library for service communication is made to be synchronous, and we want to parallelize its use.
throws null exception when HttpContext isn't set:
The obvious answer (HttpContext.Current = parentContext) can't work because there's some async code underneath (for whatever reasons), and that would cause it to sometimes not return to the same thread, and basically abandon the Context, again resulting in null
There's an important part of your question in the example code comment. :)
Normally, HttpContext shouldn't be shared across threads. It's just not threadsafe at all. But you can set HttpContext.Current (for some reason), so you can choose to live dangerously.
The more insidious problem here is that the library has a synchronous API and is doing sync-over-async - but somehow without deadlocking (?). At this point, I must be honest and say the best approach is to fix the library: make the vendor fix it, or submit a PR, or just rewrite it if you have to.
However, there is a tiny chance that you can get this kinda sorta working by adding Even More Dangerous code.
So, here's the information you need to know:
ASP.NET (pre-Core) uses an AspNetSynchronizationContext. This context:
Ensures that only one thread runs in this context at a time.
Sets HttpContext.Current for any thread that is running in the context.
Now, you could capture the SynchronizationContext.Current and install it on the thread pool threads, but in addition to being Very Dangerous, it would not achieve your actual goal (parallelization), since the AspNetSynchronizationContext only allows one thread in at a time. The first portion of the 3rd-party code would be able to run in parallel, but anything queued to the AspNetSynchronizationContext would run one thread at a time.
So, the only way I can think of making this work is to use your own custom SynchronizationContext that resumes on the same thread, and set HttpContext.Current on that thread. I have an AsyncContext class that can be used for this:
[HttpPost]
public async Task<IHttpActionResult> DoIt(IEnumerable<int> inputs)
{
var context = HttpContext.Current;
var tasks = inputs.Select(i =>
Task.Run(() =>
AsyncContext.Run(() =>
{
HttpContext.Current = context;
var results = Some3rdPartyTool.CallEndpointSynchronously(MyRestEndpointConfig[i]);
return results;
})));
var outcome = await Task.WhenAll(tasks);
}
So for each input, a thread is grabbed from the thread pool (Task.Run), a custom single-threaded synchronization context is installed (AsyncContext.Run), HttpContext.Current is set, and then the code in question is run. This may or may not work; it depends on how exactly Some3rdPartyTool uses its SynchronizationContext and HttpContext.
Note that there are several bad practices in this solution:
Using Task.Run on ASP.NET.
Accessing the same HttpContext instance simultaneously from multiple threads.
Using AsyncContext.Run on ASP.NET.
Blocking on asynchronous code (done by AsyncContext.Run and also presumably Some3rdPartyTool.
In conclusion, I again recommend updating/rewriting/replacing Some3rdPartyTool. But this pile of hacks might work.
I have async action responding to a HTTP POST via web api 1.0. I need to do 2 things when I receive this request:
Do a database insert and return the identity of that new entry to the WebApp that called the function.
Using that identity to do a whole bunch work that is I/O heavy, that they WebApp and the user don't immediately care about.
In a perfect world I would put data on a queue somewhere and have a little worker to handle the queue. Since I can't immediately do that, what is the best way to make sure this work gets done without impacting the user.
[HttpPost]
public async Task<int> Post([FromBody]Object myObject)
{
return await new ObjectLogic().InsertObject(myObject);
}
public async Task<int> InsertObject(Object myObject)
{
var id = await new ObjectData().InsertObjectRoot(myObject);
Task.Run(() => new ObjectData().ObjectWork(id, myObject));
return id;
}
This is the solution I came up but I think there has to be something better since I am bascially stealing of thread from the thread pool until my work is finished. Is there a better way? I think I could use ConfigureAwait(false) in my InsertObject method since I really dont' care about the context there.
// await async function but use ConfigureAwait
public async Task<int> InsertObject(Object myObject)
{
var id = await new ObjectData().InsertObjectRoot(myObject);
await new ObjectData().ObjectWork(id, myObject).ConfigureAwait(false);
return id;
}
One question is whether your Web API should do anything other than
receive the request
place it on a queue
response with an id to indicate that the request has been received.
It's going to depend to some degree on what sort of load you're expecting or might possibly see. But if you're concerned about the number of available threads from the outset then perhaps the answer is that your Web API does nothing but the above steps.
The queue could be a literal queue, like MSMQ (or whatever is popular now.) Or it could consist of a record inserted into a table. A separate Windows service could then process that queue and do the I/O heavy work. It doesn't even have to be on the same server. You can scale it separately.
If the user does want some eventual indication then they could poll for it at intervals using the id that you returned. But for me the key is in this statement:
Using that identity to do a whole bunch work that is I/O heavy, that the WebApp and the user don't immediately care about.
The job of a web application is to serve responses - IOW, to do what the user does care about. If it's long-running, I/O heavy work that the user doesn't care about then I'd consider offloading it.
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#.
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.
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.
You may use ConfigureAwait on public action MVC Controller, it help to prevent deal lock if your _userService.GetAuthViewModelAsync keeps waiting.
it cloud raise deadlock if async service keeps await so by may block httpcontext of UI.
Have look below link to understand this case:
http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
Using ConfigureAwait(false) in controllers does not sound good to me as it will make main thread wait until the operation is finished. The best I figured out is to use it in your Service/Business layer and Persistance layer.
I have a method that uses a repository (userRepo):
public override Task<IdentityResult> CreateLocalUserAsync(IUser user, string password, CancellationToken cancellationToken)
{
var task = new Task<IdentityResult>(() => {
TUserEntity newUser = new TUserEntity
{
Id = user.Id,
UserName = user.UserName,
Password = password
};
userRepo.Save(newUser).Flush();
return new IdentityResult(true);
}, cancellationToken);
task.Start();
return task;
}
The userRepoobject has a dependency that uses HttpContext.Current. Both of these are resolved using ninject InRequestScope.
The above method is called inside the default AccountController in Mvc 5:
var result = await IdentityManager.Users.CreateLocalUserAsync(user, model.Password);
I have tried adding this setting to web.config:
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
Also, I am definitely using .NET 4.5. This is also in my web.config:
<httpRuntime targetFramework="4.5" />
It is not possible to get the information from the HttpContext before I start the task because a dependency of the userRepo in the task is using the information and both objects are resolved using Ninject.
How can I ensure that HttpContext.Current will not be null?
The "task friendly sync context" here applies to the continuation from the await: whatever you do with result, it will have the http-context. It does not, however, relate to task.Start. That relates to the TaskScheduler, not the sync-context.
Basically, by performing this on a worker, you are (in the process, as a consequence) divorcing that worker from the http-context. You must either:
get the information you need from the http-context and pass that into the worker, or
don't use a worker
Personally, I doubt you're gaining much by pushing this onto a worker. If you really want to go async, the ideal would be for your repo to internally support *Async methods. That requires more than using threads: it usually means architectural changes, for example, using async SQL methods. Something written from the ground up to use async and sync-context-aware continuations (aka await) would automatically preserve things like the http-context.
The important difference here is that an async/await implementation is linear but not continuous, i.e.
<===(work)==>
<===(callback; more work)===>
<===(another callback)===>
where-as your existing code potentially performs things in parallel, i.e.
<==========(original work)=================>
<===========(task on worker thread)=============>
The fact that the async/await approach is basically linear makes it far more suitable for access to things like http-context, since it knows that (done right) there will only be one thread at a time accessing it - even if it isn't the same thread end-to-end.