3

这个问题与设计或模式以及使用哪个无关。这个问题的核心是关于线程和阻塞发生了什么。

此示例适用于旨在连续执行相同操作的任何阻塞方法。在这种情况下,它是对网络流的阻塞读取或写入。关于方法之间的线程和性能,幕后是否有任何明显的差异?

我的假设是下面的每个方法都会创建一个线程或使用一个池化线程。然后阻塞该线程,直到有数据要读取。话虽如此,在这种情况下,这些方法之间的线程、性能和可伸缩性是否有明显差异?

目前我正在创建一个服务器应用程序。此应用程序将有 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());
}
4

1 回答 1

1

My assumption is that each of the methods below creates a thread or uses a pooled thread. Then blocks that thread until there is data to be read.

Not at all. Your first two examples block threads, but your second two examples are asynchronous.

Asynchronous methods work by queueing the work to the OS and then waiting for a callback, in this case on an I/O completion port. So while the read is pending, there are no threads being used.

Since asynchronous approaches don't use as many threads, they scale better.

Your last example (async) is really just as simple as your first example, and that would be the approach I recommend unless you use Rx or TPL Dataflow. When doing socket communications, by the time you consider error handling such as detection of dropped connections, asynchronous communication is clearly the way to go.

于 2013-02-25T04:28:54.917 回答