这个问题与设计或模式以及使用哪个无关。这个问题的核心是关于线程和阻塞发生了什么。
此示例适用于旨在连续执行相同操作的任何阻塞方法。在这种情况下,它是对网络流的阻塞读取或写入。关于方法之间的线程和性能,幕后是否有任何明显的差异?
我的假设是下面的每个方法都会创建一个线程或使用一个池化线程。然后阻塞该线程,直到有数据要读取。话虽如此,在这种情况下,这些方法之间的线程、性能和可伸缩性是否有明显差异?
目前我正在创建一个服务器应用程序。此应用程序将有 1000 个客户端创建 tcp 连接。这些连接将保持打开状态,经常发送和接收少量数据。我希望使用模型 A,因为它最容易实现且最易于维护。无论选择哪种模式,我最终都会得到 1000 个线程吗?
请注意,这些方法只是为了给出结构的概念,而不是在没有适当的流式读取、超时和异常处理的情况下使用的东西。
方法 A:阻塞
Task.Factory.StartNew(ReadMessage,TaskCreationOptions.LongRunning);
private void ReadMessage()
{
while(true)
{
TcpClient.Read();
}
}
方法 B:睡觉
Task.Factory.StartNew(ReadMessage,TaskCreationOptions.LongRunning);
private void ReadMessage()
{
while(true)
{
if(TcpClient.DataAvailable)
TcpClient.Read();
else
Thread.Sleep(1);
}
}
方法 C:递归开始/结束
private void ReadMessage()
{
stream.BeginRead(readCallBack)
}
private void readCallBack()
{
stream.EndRead();
stream.BeginRead(readCallBack)
}
方法 D:来自 BCL 的异步 socket.ReceiveAsync()
private void readCallBack()
{
while(true)
{
await socket.ReceiveAsync(eventArgs);
}
}
方法 E:具有阻塞读取的异步方法(使用方法 D 调用,但它是一种自定义方法,而不是使用 BCL 中的内置套接字扩展)
private async Task<byte[]> ReceiveAsync()
{
return await Task.Factory.StartNew(() => TcpClient.Read());
}