Preserve HttpContext when going async with WebAPI (Medium Trust)

前端 未结 2 1193
后悔当初
后悔当初 2020-12-09 22:12

I am building a set of ASP.Net hosted WebAPI services that must use an old library which depends heavily on HttpContext.Current. I am having trouble ensuring that context i

2条回答
  •  生来不讨喜
    2020-12-09 22:51

    Context is preserved whenever you await tasks.

    What you're seeing is that there's no context for thread pool tasks (Task.Run, TaskFactory.StartNew, or for that matter BackgroundWorker or Thread or Delegate.BeginInvoke). This is normal and expected.

    So, don't use a thread pool task. Your example code seems to want to do parallel processing with multiple threads having the HttpContext, which simply isn't possible.

    You can do concurrent async methods if you want, but this requires that your Thread.Sleep can actually be an async method instead of a CPU-based method:

    [HttpGet]
    public async Task> Test()
    {
      Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
      Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
    
      var output = new List { TestOutput("Action start") };
    
      var task = SlowStringAsync();
      output.Add(TestOutput("Action Mid"));
      output.Add(await task);
      output.Add(TestOutput("Action end"));
      return output;
    }
    
    public async Task SlowStringAsync()
    {
      await Task.Delay(1000);
      return TestOutput("In Task");
    }
    

    If your old library is out of your control and you can't make it async, then you'll have to call it synchronously. It's acceptable to call a synchronous method from an async method in situations like this:

    [HttpGet]
    public async Task> Test()
    {
      Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
      Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
    
      var output = new List { TestOutput("Action start") };
    
      output.Add(TestOutput("Action Mid"));
      Thread.Sleep(1000);
      output.Add(TestOutput("Not Really In Task"));
      output.Add(TestOutput("Action end"));
      return output;
    }
    

提交回复
热议问题