我应该将工作卸载到 ASP.NET 中的其他线程吗?

cme*_*ren 5 .net asp.net multithreading asynchronous async-await

我正在创建 ASP.NET Web API,其中某些操作(同步、遗留代码)可能需要一些时间(主要是 IO 限制,但也有一些计算密集型的东西)。

我知道每个传入请求都从线程池中分配了一个线程,但我对其余部分有点模糊。请求线程是否以某种方式“特殊”,保证将工作卸载到其他线程以避免锁定它?卸载对线程池饥饿和拒绝请求有帮助吗?如果是这样,我是否需要一直为每个可能长时间运行的函数创建一个异步包装器,还是只需要一个最高级别的异步包装器?

cme*_*ren 5

为长时间运行的任务创建异步包装器在 ASP.NET 上下文中毫无意义,而且除了在多个方面损害性能之外没有任何作用。

\n\n

当卸载 GUI 线程或另一个特殊线程时,在线程池线程上异步运行同步方法是有意义的。在这种情况下,该方法应该由调用者在该特殊线程上以调用者认为合适的任何方式异步调用(使用eg Task.Run,通常不应在异步方法的实现中使用)。然而,在 ASP.NET 中,只有线程池线程,并且出于多种原因不需要(实际上不应该)以这种方式卸载线程。

\n\n

Stephen Cleary(毕竟,他写了一本关于 C# 并发的书)在博客文章Task.Run Etiquette Examples: Don\t Use Task.Run in the Implementing 中对此说得最清楚

\n\n
\n

这就是为什么 ASP.NET 的原则之一是避免使用线程池线程(当然,ASP.NET 为您提供的请求线程除外)。更重要的是,这意味着ASP.NET 应用程序应该避免Task.Run.

\n\n

[...]

\n\n

事实上,我们唯一真正需要异步计算的地方是当我们从 UI 线程调用它时。

\n
\n\n

强烈推荐整篇文章,重点介绍了 ASP.NET 中卸载的各种问题。

\n\n

进一步阅读:

\n\n\n