C# 不使用线程处理多个TcpClient连接

C# 不使用线程处理多个TcpClient连接,c#,.net,tcpclient,single-threaded,C#,.net,Tcpclient,Single Threaded,我有一个C#程序,其中有很多(比如说大约一千个)打开的TcpClient对象。我想进入一个状态,等待这些连接中的任何一个发生某些事情 我宁愿不要为每个连接启动一个线程 类似于 while (keepRunning) { // Wait for any one connection to receive something. TcpClient active = WaitAnyTcpClient(collectionOfOpenTcpClients); // One

我有一个C#程序,其中有很多(比如说大约一千个)打开的TcpClient对象。我想进入一个状态,等待这些连接中的任何一个发生某些事情

我宁愿不要为每个连接启动一个线程

类似于

while (keepRunning)
{
     // Wait for any one connection to receive something.
     TcpClient active = WaitAnyTcpClient(collectionOfOpenTcpClients);

     // One selected connection has incomming traffic. Deal with it.
     // (If other connections have traffic during this function, the OS
     // will have to buffer the data until the loop goes round again.)
     DealWithConnection(active);
}
其他信息:
TcpClient对象来自TcpListener。
目标环境将是Linux上的MS.NET或Mono。

该协议在连接打开时调用长时间的空闲状态。

在Microsoft术语中,您尝试执行的操作称为异步模式。总体思路是将所有I/O阻塞操作更改为非阻塞操作。如果这样做,应用程序通常需要与机器上CPU核数量相同的系统线程

请看一下.Net 4中的任务并行库:

它是一个相当成熟的包装器,超越了简单的老Begin/Callback/Context.Net范式

更新:

思考在从连接读取数据后,您将如何处理这些数据。在现实生活中,您可能需要回复客户机或将数据保存到文件中。在这种情况下,您将需要一些C#基础结构来包含/管理您的逻辑,并且仍然保持在单个线程中。TPL为您免费提供。它唯一的缺点是它是在.NET4中引入的,所以它可能还没有出现在Mono中


另一个需要考虑的是连接的寿命。您的连接多久打开/关闭一次,有效期多长?这一点很重要,因为接受和断开TCP连接需要与客户端进行数据包交换(本质上是异步的,而且恶意客户端可能根本不会返回确认的数据包)。如果您认为这一点对您的应用程序非常重要,您可能需要研究如何在.Net中正确处理这一点。在WinAPI中,相应的函数是AcceptEx和DisconnectEx。可能它们是用Begin/End方法包装在.Net中的——在这种情况下,您就可以开始了。否则,您可能必须在这些WinAPI调用上创建一个包装器。

在Unix世界中,您可以使用
select
syscall来完成此操作。我相信Windows中也有类似的功能。你假设的“每个连接都有一个线程”是有缺陷的。线程池加上APM方法是解决此类问题的方法。仅仅几个线程就可以为许多客户机提供服务。我给出的这个答案应该很有启发性:@spender-你建议我开始处理所有~1000个TCP客户,并处理回拨中的任何流量?如果你想把它写进答案,我会接受的。