0

I have an async method, which uses HttpContext.Current, which is used by another code, which is running in background, like

var result = Task.Run(async () => await SomeMethod()).Result;

HttpContext.Current is always null though. Is there a way to pass HttpContext into background task?

user2820173
  • 308
  • 2
  • 13
  • Sounds like it's been referenced before: https://stackoverflow.com/questions/8925227/access-httpcontext-current-from-different-threads – JohnPete22 Mar 24 '21 at 12:01
  • 1
    More recent https://stackoverflow.com/questions/63413283/how-to-pass-httpcontext-to-the-new-thread-c-sharp .... according to the answer there is a way to do that, but it is not advisable because HttpContext is not thread safe. – Goodies Mar 24 '21 at 12:02
  • If it's truly a "background task" then why would it need access to an HttpContext in the first place? The whole idea of a background task would be that it's happening outside of an HttpContext. – mason Mar 24 '21 at 14:17
  • I launched it as background task to prevent deadlock. – user2820173 Mar 24 '21 at 14:20
  • Then you're barking up the wrong tree. In most cases, if you're using .Result, Task.Run, or .Wait(), those are strong signs that you need to double check your asynchronous patterns. If you want to call an asynchronous method, in most cases you should just `await` it. – mason Mar 24 '21 at 14:23
  • We're using framework, which doesn't allow async methods in some places. Should we go all way sync in those places? – user2820173 Mar 24 '21 at 14:26
  • What do you mean you're "using framework"? What framework? Be specific! And if you want to reply to me, make sure to @mention me as the notifications usually only go to whoever made the post. – mason Mar 24 '21 at 14:42
  • @mason we are using a cms framework, which requires as to override some methods, which have sync signatures only – user2820173 Mar 24 '21 at 14:46
  • Okay, so lets get some more context here. What are you trying to accomplish with these async calls? Just make an HTTP call to somewhere and get a response, which you will then use in processing the request? Or are you trying to initiate some long running process that you don't want the user to have to wait for? – mason Mar 24 '21 at 14:49
  • @mason it's short http call, which will be used in response – user2820173 Mar 24 '21 at 14:55
  • Okay, so background processing is not appropriate. Is there a newer version of the CMS framework you can update to that has async support? Have you checked the documentation for it on how they recommend to do async? Any notes in their forums on how others have approached it with that framework? – mason Mar 24 '21 at 15:02
  • afaik no async support yet. I will try to research more. – user2820173 Mar 24 '21 at 15:30

1 Answers1

5

Is there a way to pass HttpContext into background task?

Technically yes, you can set HttpContext.Current. However, you really don't want to do this. HttpContext is intended for use by only one thread at a time.

A better solution is to remove the Task.Run entirely:

await SomeMethod();

Task.Run shouldn't be used on ASP.NET in the first place.

It looks like the code may be trying to use Task.Run to do a "fire and forget", in which case Task.Run is a very dangerous and incomplete "solution". The proper solution for fire-and-forget is asynchronous messaging, i.e., a durable queue with a separate background service.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • Sorry, I updated my code, as I'm getting the result back. If I do (await SomeMethod()).Result, then this seems to hang forever. – user2820173 Mar 24 '21 at 12:25
  • 1
    [Don't block on asynchronous code](https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html); use [`async` all the way](https://learn.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming). In other words, use `await` instead of `Result`. – Stephen Cleary Mar 24 '21 at 12:33
  • That's not possible due to framework we're using. Should I go sync all the way? The http call we're making would block ui for a while, though. – user2820173 Mar 24 '21 at 14:07
  • 1
    @user2820173 What do you mean due to the framework? Which framework do you think prevents async? And either way, the UI is going to be blocked here, unless you truly run in the background (which won't have access to an HttpContext). The way ASP.NET is different from desktop programming like Windows Forms. Once all the server side code has been executed (except background work) then the HTTP response will be sent to the client browser, at which point the client can rerender itself. – mason Mar 24 '21 at 14:38
  • @user2820173 If you've got some sort of long running logic that needs to run in the background, then you may be interested in Hanselman's [blog post about background tasks](https://www.hanselman.com/blog/how-to-run-background-tasks-in-aspnet). Though my own recommendation is to move that logic entirely out of your web app into a Window service or an Azure Function or some other sort of different application. Web apps are for servicing HTTP requests and providing them with responses - they don't do well with long running background processing. – mason Mar 24 '21 at 14:40
  • we are using a cms framework, which requires as to override some methods, which have sync signatures only. – user2820173 Mar 24 '21 at 14:40
  • 2
    @user2820173: Then you should go sync all the way. – Stephen Cleary Mar 24 '21 at 14:59