提问者:小点点

当您使用Task.run太多以至于线程池耗尽时会发生什么?


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

我一直在使用nito.asyncex库的AsyncContext Run方法,但我对从EndRead调用它是否会阻塞,从而使工作线程成为人质持保留态度。对于前面的问题,我得到的建议是使用Task.run而不是Nito.Asyncex的AsyncContext.run。这会将调用提交到async/await代码中,并立即返回。我突然想到,在负载情况下,客户端没有反推来防止请求淹没线程池。

我将重新提出我最初关于Nito.AsyncEx's AsyncContext.Run的问题:它是将它调用的线程(池线程调用我的套接字的EndRead回调)作为人质,还是在它调用的异步I/O在后台发生时释放该线程?

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


共2个答案

匿名用户

的目的是阻止,直到所有异步操作完成为止。它确实会保留线程,直到发生这种情况。

我建议你重新考虑到目前为止的每一个假设:

    回调。/li>

如果您确定确实需要实现自己的TCP/IP服务器,并且在回调中无法同步完成工作,那么您确实需要节流。。。然后考虑反应性扩展或TPL数据流。这两个库都有可选的内置节流功能。

匿名用户

这取决于您的应用程序到底在做什么。下面是一些场景:

您正在处理来自每个客户端的数据流

每个客户机发送一些数据,服务器在每条消息传入时处理它。在这种情况下,可能不需要在单独的线程中运行处理。当您阻塞时,TCP堆栈正在建立一个缓冲区供您读取。如果剩余缓冲区大小太小,TCP堆栈将向客户端发送窗口大小警告。

客户端可能会发送一系列消息,每个消息都需要长时间的处理

客户端以突发方式向服务器发送消息。每个消息都需要相当长的时间来处理。以串行方式处理消息会导致大量的TCP重试,从而产生问题。在本例中,启动,不必担心耗尽线程池。

null

处理来自客户端的消息是很耗时的,而且客户端实际上发送的工作可能比您所能处理的更多。在这种情况下,您可能需要某种特定于应用程序的流控制。客户端可能需要在发送消息之前轮询服务器状态。如果客户无论如何发送,您将被迫忽略这些信息。

相关问题