c# - 长时间运行的阻塞方法。阻塞、休眠、开始/结束和异步之间的区别

标签 c# blocking networkstream thread-sleep

这个问题不是关于设计或模式以及使用哪个。这个问题的核心是关于线程和阻塞的情况。

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

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

目前我正在创建一个服务器应用程序。此应用程序将有 1000 个客户端创建 TCP 连接。这些连接将保持打开状态,经常发送和接收少量数据。我希望使用模型 A,因为它最容易实现且最易于维护。无论选择哪种模式,我最终都会得到 1000 个线程吗?

请注意,这些方法只是为了提供结构的概念,而不是在没有适当的流式读取、超时和异常处理的情况下使用的东西。

方法A:阻塞

Task.Factory.StartNew(ReadMessage,TaskCreationOptions.LongRunning);
private void ReadMessage()
{
   while(true)
   {
      TcpClient.Read();
   }
}

方法B: sleep

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());
}

最佳答案

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.

完全没有。您的前两个示例阻止线程,但您的后两个示例是异步的。

异步方法的工作原理是将工作排队到操作系统,然后等待回调,在本例中是在 I/O 完成端口上。因此,当读取挂起时,没有线程被使用。

由于异步方法不使用尽可能多的线程,因此它们的扩展性更好。

您的最后一个示例 (async) 实际上与您的第一个示例一样简单,除非您使用 Rx 或 TPL 数据流,否则我将推荐这种方法。在进行套接字通信时,当您考虑错误处理(例如检测断开的连接)时,异步通信显然是可行的方法。

关于c# - 长时间运行的阻塞方法。阻塞、休眠、开始/结束和异步之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15059674/

相关文章:

c# - Java 的 getClass()、isAssignableFrom() 等的 c# 等价物是什么?

java - 为什么 InputStreamReader read() 阻塞而不是返回 -1?

c# - 当发送大于SendBufferSize的数据时,如何接收数据?

c# - 使用 TCP 在 C# 中实现 FTP 客户端

javascript - 如何使用 jquery ajax 调用将文件以及其他字段的数据发送到 webmethod is asp.net?

c# - 如何使用代码迁移配置禁用延迟加载,Entity Framework 4.1

c# - 从字符串中获取枚举字段

python - "blocking"这个词在编程中是什么意思?

sockets - 非阻塞套接字轮询与阻塞套接字

c# - NetworkStream ReadAsync 和 Read 同一个方法