Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Friday, November 4, 2016 11:41 AM
Here is the code:
public async Task<IHttpActionResult> Get()
{
bool result = await Task.Run(()=>{
string UserHostAddress = System.Web.HttpContext.Current.Request.UserHostAddress;
})
/***************please ignore code below, just for the code integrity***************/
if(!result) return BadRequest();
return Ok();
}
This code previously mentioned, get exception Object reference not set to an instance of object;
Question A:
why does't async's context load the HttpContext data?
Question B:
what does the async's context load?
Question C:
What does the async's context ignore If I set the ConfigureAwait(continueOnCapturedContext:false);
All replies (7)
Tuesday, November 8, 2016 3:35 PM ✅Answered
HttpContext.Current will return a HttpContext object, and it's stored in CallContext.HostContext property, you can use following code to verify:
protected void Page_Load(object sender, EventArgs e)
{
HttpContext context1 = HttpContext.Current;
HttpContext context2 = System.Runtime.Remoting.Messaging.CallContext.HostContext as HttpContext;
Response.Write(object.ReferenceEquals(context1, context2));
}
According to MSDN article https://msdn.microsoft.com/en-us/library/system.runtime.remoting.messaging.callcontext.hostcontext(v=vs.110).aspx
This property is used to gets or set the host context associated with the current thread.
How to understand 'the current thread' in above MSDN description?
Because ASP.NET will arrange a thread for each request, and this thread will execute the code to produce the response result, even the code is distributed in different class libraries, the thread will also execute them, so we can access HttpContext.Current to get the HttpContext object associated with THE CURRENT THREAD, after all, those code is executed by the same thread, so the reference to HttpContext is the object which is associated with the request.
For 'the current thread', it's 'the current request' related thread, but in ASP.NET, NOT all threads are related to request. For example, create background thread or hand the task over thread pool to handle, in that scenario, HttpContent.Current will return null, as it is not associated with any request at all.
I think you almost never want to use Task.Run in an ASP.NET method, Task.Run will negate all the performance benefits of async and then degrade performance. If you still want to use Task.Run, following solution is for your reference:
Manually get the value outside Task.Run:
public async Task<IHttpActionResult> Get()
{
string UserHostAddress = System.Web.HttpContext.Current.Request.UserHostAddress;
bool result = await Task.Run(()=>{
// you can se UserHostAddress here
})
/***************please ignore code below, just for the code integrity***************/
if(!result) return BadRequest();
return Ok();
}
Some threads discussing the similar scenarios can be found as follows:
http://stackoverflow.com/questions/13748267/using-httpcontext-in-async-task
Wednesday, November 9, 2016 5:56 AM ✅Answered
It's explained in following thread which is in my previous post.
Regarding this topic (Task.Run vs async/await), I'm sharing you some useful links, hope they can help you understand the overall map.
Async/Await - Best Practices in Asynchronous Programming
Asynchronous Programming with async and await (C#)
Why you shouldn’t create asynchronous wrappers with Task.Run()
And there are many threads discussing this, like following:
http://stackoverflow.com/questions/32606485/calling-an-async-method-using-a-task-run-seems-wrong
http://stackoverflow.com/questions/18013523/when-correctly-use-task-run-and-when-just-async-await
Friday, November 4, 2016 12:50 PM
You need to pass the HttpContext to the async method like below
public async Task<bool> Testing(HttpContext currentContext)
{
bool result = await Task.Run(() =>
{
string UserHostAddress = currentContext.Request.UserHostAddress;
return true;
});
return result;
}
I believe that the purpose of async methods are to run in the background thread. So HttpContext will not be available in those methods.
Friday, November 4, 2016 2:14 PM
The context.current is tied to the current thread, but task run starts a new thread, without context setup.
Saturday, November 5, 2016 1:16 AM
here are my confused points:
1. if I didn't set up the ConfigureAwait(continueOnCapturedContext:false), the async thread must remember the original context back-trip point. if async thread remember the original context , why it can't call the current.
2. if I set up the System.Web.HttpContext a = new System.Web.HttpContext(System.Web.HttpContext.Current.Request,System.Web.HttpContext.Current.Response); at outside of the Task.Run. it can run very well and as my expect. why the mechanism run like this, I mean the System.Web.HttpContext.Current.Request,UserHostAddress is a constant, the "a" I declared is also a constant. why the async can't capture the System.Web.HttpContext.Current.Request,UserHostAddress, but can capture the "a" I declared previously.
Wednesday, November 9, 2016 1:51 AM
Thank you very much for your perfect answer,
With your answer above in mind, I may want to bother you to explain another question: how should I understand the Task.Run will negate all the benefit performance of async?
Thank you.
Saturday, November 19, 2016 10:44 AM
Sorry about the late mark as answer, I know your answer is so important that I can't slur those article. so , I must pick up one comfortable moment to read your answer.
Thank you.