.net - 当你使用 Task.Run 太多以至于线程池耗尽时会发生什么?

标签 .net task-parallel-library threadpool async-await

我有一个 .NET Windows 服务,它使用 BeginRead/EndRead 异步 I/O 范例实现套接字服务器。现在这个套接字代码需要调用一些 async/Task/await 异步代码。

我一直在使用 Nito.AsyncEx 库的 AsyncContext 类的 Run 方法,但我对从 EndRead 调用该方法是否会阻塞并劫持工作线程持有保留意见。我得到的建议my earlier question是使用 Task.Run 而不是 Nito.AsyncEx 的 AsyncContext.Run。这会将调用提交到 async/await 代码并立即返回。我突然想到,在负载下,客户端没有任何回退来防止请求淹没线程池。

我将重新问我原来关于 Nito.AsyncEx 的 AsyncContext.Run 的问题:它是否持有它调用的线程(调用我的套接字的 EndRead 回调的池线程)人质,或者它是否在异步时释放该线程它正在调用的 I/O 在后台发生?

如果 Nito.AsyncEx 的 AsyncContext.Run 真的阻塞,那么 Task.Run 似乎是我唯一的选择。关于如何推迟客户端请求以防止线程池耗尽的任何建议?

最佳答案

AsyncContext.Run 的目的是阻塞,直到所有异步操作完成。它确实会保持线程直到发生这种情况。

我建议您重新考虑目前的每一个假设:

  1. 你真的需要套接字服务器吗?围绕 TCP/IP 套接字存在大量的陷阱。严重地。 很多。有什么方法可以让您自行托管 WebAPI 吗?它比套接字服务器更容易开始工作。
  2. 为什么需要将工作推到线程池线程上? End* 回调已在线程池线程上调用。
  3. 你确定你需要节流吗?没有代码可以阻止动机充分的 DoS 攻击。

如果您确定确实需要实现自己的 TCP/IP 服务器,并且无法在回调中同步完成工作,并且确实需要节流……那么请考虑 Reactive ExtensionsTPL Dataflow .这两个库都内置了可选的节流功能。

关于.net - 当你使用 Task.Run 太多以至于线程池耗尽时会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21340273/

相关文章:

c# - 如何在不使用 EF 的情况下使用 Breeze 保存更改?

c# - 在 ASP.NET MVC 包中使用 CDN

c# - 从 XML 元素中读取空格字符

.net - 构建任务之前是否有 .NET Core CLI pre?

c# - 限制没有。每秒由 Dns.BeginGetHostEntry 方法生成的请求数或使用任务并行库 (TPL)

c# - 将 func<type, bool> 作为参数传递给异步方法时出错

c# - 带有 lambda 表达式和匿名方法的 ThreadPool.QueueUserWorkItem

vb.net - 在多个线程中运行不同的进程而不会在VB.NET 2中重叠

c# - Thread Join() 导致 Task.RunSynchronously 未完成

c# - CancellationTokens 可以跨 AppDomains 使用吗