gpt4 book ai didi

asp.net - Web API服务-如何在异步任务中使用 "HttpContext.Current"

转载 作者:行者123 更新时间:2023-12-04 05:50:16 24 4
gpt4 key购买 nike

我正在使用webApi rest服务的“发布”异步方法:

public async Task<object> Post([FromBody]string data)
{
object response = ExecuteServerLogics(data);

return response;
}

上面的代码很好用,但是在一些客户的电话中,我们遇到了性能问题。

在这里阅读了一些文章之后,我注意到我们的webApi rest服务,
与其传入的Web请求并不是真正地异步工作,
因为我们忘记了使用 async/await模式:
public async Task<object> Post([FromBody]string data)
{
object response = await Task<object>.Run( () =>
{
return ExecuteServerLogics(data);
});

return response;
}

修复此问题后,我们注意到性能有所提高,
但我们发现了另一个批评者问题:
当访问 HttpContext.Current 时-返回Null引用:
public async Task<object> Post([FromBody]string data)
{
object response = await Task<object>.Run( () =>
{
var currentContext = HttpContext.Current; // Returns Null!
return ExecuteServerLogics(data);
});

return response;
}

我们试图找到一种解决方案,在大多数帖子中,我们发现我们应该通过
工作线程的 HttpContext 引用到执行服务器逻辑的内部Task中。
此解决方案的问题在于服务器的逻辑方法使用许多静态类,这些类使用
“HttpContext.Current” ,例如-
  • Loggers调用。
  • 检索用户的静态安全类。
  • 检索传入请求的 session 数据等的静态安全性类。

  • 因此,传递辅助线程的 “HttpContext.Current” 引用将无法解决该问题。

    当我们尝试下一个解决方案时:
    public async Task<object> Post([FromBody]string data)
    {
    // Save worker context:
    var currentContext = HttpContext.Current;

    object response = await Task<object>.Run( () =>
    {
    // Set the context of the current task :
    HttpContext.Current = currentContext ; // Causes the calls not to work asynchronously for some reason!

    // Executes logics for current request:
    return ExecuteServerLogics(data);
    });

    return response;
    }

    由于某种原因,我们注意到性能再次变差,就像它又恢复了同步工作一样。

    我们的问题是:

    1. 为什么在上一个示例中,在await任务中设置 “HttpContext.Current”
    导致请求返回与 同步结果相似的不良性能结果?

    2. 还有另一种方法可以在内部任务内部使用 “HttpContext.Current” -“ExecuteServerLogics”,
    并且在所有静态类中也将 称为“HttpContext.Current”
    我是否以某种方式对整个设计做错了?

    谢谢!

    最佳答案

    从一开始就:

    public async Task<object> Post([FromBody]string data)
    {
    object response = ExecuteServerLogics(data);
    return response;
    }

    不要忽略编译器警告;编译器将为此方法生成一条警告,明确指出它将同步运行。

    继续:

    in some of the client's calls, we experienced performance issues.



    对于隔离中的单个调用,服务器上的异步代码将不会更快。它仅可帮助您扩展服务器。

    特别是, Task.Run将抵消 async的所有性能优势,然后使性能进一步下降。我相信您衡量的性能改善是偶然的。

    in most posts we found that we should pass the worker thread's HttpContext reference into the inner Task that executes the server logics.



    这些帖子是错误的。恕我直言。当该对象专门设计为只能从请求线程访问时,最终会从后台线程使用 HttpContext对象。

    am I doing the entire design wrong somehow?



    我建议您退后一步,考虑一下大局。收到请求时,它需要做一些工作。该工作是同步完成还是异步完成对客户而言并不重要。两种方法将花费大约相同的时间。

    如果您需要尽早返回客户,那么您将需要一个完全不同的体系结构。通常的方法是将工作排队到可靠的队列(例如Azure队列),具有单独的后端(例如Azure WebRole),并在工作完成时主动通知客户端(例如SignalR)。

    但这并不是说 async是没有用的。如果 ExecuteServerLogics是受I/O约束的方法,则应使其成为异步方法而不是阻塞方法,然后可以这样使用异步方法:
    public async Task<object> Post([FromBody]string data)
    {
    object response = await ExecuteServerLogicsAsync(data);
    return response;
    }

    这将使您的服务器整体上具有更高的响应能力和可扩展性(即不会被很多请求所淹没)。

    关于asp.net - Web API服务-如何在异步任务中使用 "HttpContext.Current",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23790292/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com