微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

asp.net – 与WebAPI异步时保留HttpContext(中等信任)

我正在构建一组ASP.Net托管的WebAPI服务,必须使用一个很大程度上依赖于HttpContext.Current的旧库.我无法确保在参与异步调用的所有方法中保留上下文.我在下面的代码中尝试了await / Task.Wait和TaskScheduler.FromCurrentSynchronizationContext()的几个变体.
[HttpGet]
    public Task<IEnumerable<string>> ContinueWith()
    {
        Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");  //or another culture that is not the default on your machine
        Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;

        var output = new List<string> { TestOutput("Action start") };

        var task = Task.Factory.StartNew(() =>
            {
                Thread.Sleep(1000);
                return TestOutput("In Task");
            }).ContinueWith(slowString =>
            {
                output.Add(slowString.Result);

                output.Add(TestOutput("Action end"));
                return output as IEnumerable<string>;
            });

        output.Add(TestOutput("Action Mid"));

        return task;
    }

    private string TestOutput(string label)
    {
        var s = label + " ThreadID: " + Thread.CurrentThread.ManagedThreadId.ToString(CultureInfo.InvariantCulture);
        s += " " + Thread.CurrentThread.CurrentCulture.EnglishName;
        s += HttpContext.Current == null ? " No Context" : " Has Context";
        Debug.WriteLine(s);
        return s;
    }

我希望能够确保CurrentCulture是fr-FR,并且在调用TestOutput的每个点上HttpContext.Current都不为null.我没有成功地使用我尝试的任何东西进行“In Task”调用.另外在我的一些测试线程中,id永远不会变化,这表明我已经有效地删除了该方法的异步性.如何确保在每次调用TestOutput时都保留culture和HttpContext.Current,并且代码可以在不同的线程上自由运行?

在闭包中捕获HttpContext.Current然后再次设置它将不适合我,因为我需要支持Medium Trust,它会在调用HttpContext.Current setter时抛出安全异常.

解决方法

等待任务时,将保留上下文.

你所看到的是没有线程池任务的上下文(Task.Run,​​TaskFactory.StartNew,或者对于BackgroundWorker或Thread或Delegate.BeginInvoke).这是正常的和预期的.

所以,不要使用线程池任务.您的示例代码似乎想要使用具有HttpContext的多个线程进行并行处理,这是不可能的.

如果需要,可以执行并发异步方法,但这要求您的Thread.Sleep实际上可以是异步方法而不是基于cpu方法

[HttpGet]
public async Task<IEnumerable<string>> test()
{
  Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
  Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;

  var output = new List<string> { 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<string> SlowStringAsync()
{
  await Task.Delay(1000);
  return TestOutput("In Task");
}

如果您的旧库不受您的控制,并且您无法使其异步,那么您必须同步调用它.在以下情况下从异步方法调用同步方法是可以接受的:

[HttpGet]
public async Task<IEnumerable<string>> test()
{
  Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
  Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;

  var output = new List<string> { 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;
}

原文地址:https://www.jb51.cc/aspnet/247029.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐