【问题标题】:C# wrapping blocking io with task to make asyncC# 用任务包装阻塞 io 以进行异步
【发布时间】:2014-01-21 21:31:36
【问题描述】:

我有一个 web api 调用,我想获得很大的吞吐量,所以我用一个 Task 包装 I/O,希望让它异步。但是,我不确定它是否要我寻找。

public HttpResponseMessage Post([FromBody]DataRequest request)
    {
        Task.Factory.StartNew(() =>
        {
            service.SendRequestToQueue(request);
        });

        return Request.CreateResponse(HttpStatusCode.Accepted);
    }

我觉得这不是正确的做法。它确实从请求线程中获取 I/O,但仍由应用程序中的线程而不是内核处理。我对吗?除了使异步和一直等待之外,还有更好的方法吗?

【问题讨论】:

  • 并非如此。您通常应该完全同步或完全异步。 Async over sync(就是这样)或 sync over async(在异步操作上同步阻塞)都是非常有问题的,应该不惜一切代价避免。
  • 这究竟是什么原因?看起来客户端只是发送请求而不等待结果?如果是这种情况,那么这是一种很好的方法。我不确定为什么 Servy 认为您应该不惜一切代价避免使用异步方法。这似乎不是一个合理的说法。显然,如果您要开始异步工作,您将暴露一组新问题,但 async await 可用是有原因的。如果您的意图是击中它并忘记它,那么这是一个很好的解决方案。但是如果你需要等待结果。只需使用异步等待。
  • @Callan:这不是一个好的解决方案; it's very dangerous,正如我在博客中解释的那样。
  • 我认为这是一篇很棒的博文。我只是假设他不在乎结果是什么。在子线程中抛出异常可以关闭应用程序池,但通过适当的异常处理,他不必担心它。当然,在绝大多数情况下,您需要等待结果,创建子线程并等待它返回是没有意义的。但是在关闭更改时,他真的不在乎返回什么,这将是一种将工作发送到服务器并忘记它的可行方法。但我同意,这方面的用例很少。

标签: c# multithreading asynchronous io task-parallel-library


【解决方案1】:

正如@Servy 评论的那样,正确的解决方案是一直使用async。特别是在 ASP.NET 上,您应该避免使用Task.RunTask.Factory.StartNew。正如您所怀疑的,将await 与排队到线程池的任务一起使用根本不会给您带来任何可伸缩性优势。

您当前的代码返回响应,同时继续在内存中处理请求。这是非常危险的,正如我所解释的 on my blogin a recent CodeMash talk(请参阅标题为“提前返回”的“陷阱”部分下的幻灯片)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-07
    • 1970-01-01
    • 2014-09-25
    • 1970-01-01
    • 2011-05-07
    相关资源
    最近更新 更多