【问题标题】:Confusion about calling CPU-bound methods synchronously from an async method关于从异步方法同步调用 CPU 绑定方法的困惑
【发布时间】:2015-08-04 21:36:10
【问题描述】:

我对 .NET 4.5 的 async/await 结构感到很困惑。我正在开发一个 RESTful Web API 解决方案。我试图弄清楚如何处理受 CPU 限制的操作 - 1) 从当前线程同步调用它,或者 2) 使用 Task.Run()?

让我们使用来自page 的示例:

async Task<int> AccessTheWebAsync()
{ 
    // You need to add a reference to System.Net.Http to declare client.
    HttpClient client = new HttpClient();

    // GetStringAsync returns a Task<string>. That means that when you await the 
    // task you'll get a string (urlContents).
    Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

    // You can do work here that doesn't rely on the string from GetStringAsync.
    DoCPUBoundWork();

    // The await operator suspends AccessTheWebAsync. 
    //  - AccessTheWebAsync can't continue until getStringTask is complete. 
    //  - Meanwhile, control returns to the caller of AccessTheWebAsync. 
    //  - Control resumes here when getStringTask is complete.  
    //  - The await operator then retrieves the string result from getStringTask. 
    string urlContents = await getStringTask;

    // The return statement specifies an integer result. 
    // Any methods that are awaiting AccessTheWebAsync retrieve the length value. 
    return urlContents.Length;
}

在这里,让我们假设DoCPUBoundWork() 严格受 CPU 限制并且不涉及任何类型的 IO。

如图所示从当前线程调用它是最佳做法吗?

还是有以下更好?

await Task.Run(() => DoCPUBoundWork()).ConfigureAwait(false);

我已经阅读了克利里先生的一些帖子,并且收到了一些混杂的建议。在这个post 中,他建议最好同步调用CPU 绑定的东西以避免async/await/Task.Run() 的不必要开销。但是,在这个post 中,他建议将Task.Run() 用于CPU 绑定操作,而无需提及任何异常情况。我确定我遗漏了一些明显的东西。希望得到一些澄清。

【问题讨论】:

  • DoIndependentWork 通常运行多长时间?
  • 假设它需要足够长的时间在高负载下引起问题......

标签: c# asp.net .net async-await task-parallel-library


【解决方案1】:

如图所示从当前线程调用它是最佳做法吗?

如果您当前的线程在异步操作进行时是空闲的,为什么要使用不同的线程?是什么让 那个 线程比你已经在使用的线程更好?

关于DoIndependentWork 实际在做什么的问题浮现在脑海中。如果它在 HTTP 请求完成之前完成很重要,我会同步调用它。如果在 HTTP 请求完成之前完成这项工作并不重要,那么我会寻找一个完全不同的解决方案。在 ASP.NET 中使用 Task.Run 是危险的。

请记住,ASP.NET 中的延续在任意线程池线程上运行。

【讨论】:

  • 那么...什么时候使用 Task.Run() 将其卸载到另一个线程才有意义? (我很困惑为什么 Stephen Cleary 在他的博客中建议使用 Task.Run() 来处理 CPU 绑定的内容)
  • wpf 中的 ui-bound threads 怎么样?触发额外任务以避免阻塞 gui 是可行的......
  • @Andreas 你是对的,如果这是 WPF,我会提出不同的建议。但这是 ASP.NET,这是不同的。
  • @Zoomzoom 在 ASP.NET 中,您甚至不应该使用 Task.Run。它不会注册工作,并且 IIS 可能会在执行时回收您的应用程序。在基于 UI 的应用程序中使用 Task.Run 更有意义,我假设这就是 Stephan 所指的。
  • 我应该读过他博文下的 cmets。有人已经问过同样的问题,斯蒂芬确实说了一些同意你的话。
猜你喜欢
  • 2021-09-25
  • 2017-09-23
  • 2020-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多