在NetworkStream上读取= 100%的CPU使用率

Sea*_*n P 4 .net c# sockets networkstream cpu-usage

我正在从一个在while循环中的NetworkStream中读取.问题是我看到100%的CPU使用率.有没有办法阻止这种情况发生?

这是我到目前为止:

    while (client != null && client.Connected)
            {

                NetworkStream stream = client.GetStream();
                data = null;

                try
                {
                    // Check if we are still connected.
                    if (client.Client.Poll(0, SelectMode.SelectRead))
                    {
                        byte[] checkConn = new byte[1];

                        if (client.Client.Receive(checkConn, SocketFlags.Peek) == 0)
                        {
                            throw new IOException();
                        }
                    }

                    if (stream.DataAvailable)
                    {
                        //Read the first command
                        WriteToConsole("Waiting for next command");
                        data = ReadStringFromClient(client, stream);
                        WriteToConsole("Received Command: " + data);
                    }
                }
Run Code Online (Sandbox Code Playgroud)

......代码继续......

ReadStringFromClient代码:

   private string ReadStringFromClient(TcpClient clientATF, NetworkStream currentStream)
    {
        int i;
        string builtString;
        byte[] stringFromClient = new byte[256];

        if (clientATF.Connected && currentStream.CanRead)
        {

            i = currentStream.Read(stringFromClient, 0, stringFromClient.Length);
            builtString = System.Text.Encoding.ASCII.GetString(stringFromClient, 0, i);

        }

        else
        {
            return "Connection Error";
        }

        return builtString;

    }
Run Code Online (Sandbox Code Playgroud)

dtb*_*dtb 9

你的代码包含很多......噪音.你不需要它.

100%CPU负载的原因是您在等待数据变得可用.你不需要这样做.Read将阻止,直到数据可用.您也不需要NetworkStream为每个要接收的数据块重新创建.

如果您使用StreamReader,您的代码可以大大简化:

using (var reader = new StreamReader(new NetworkStream(socket))
{
    char[] buffer = new char[512];
    int received;
    while ((received = reader.Read(buffer, 0, buffer.Length)) > 0)
    {
        string s = new string(buffer, 0, received);
        Console.WriteLine(s);
    }
}
Run Code Online (Sandbox Code Playgroud)

Read阻止,直到数据可用.连接处于活动状态时代码循环.如果使用ReadLine而不是读入char缓冲区,则可以进一步简化代码.

如果您不希望在数据可用之前阻塞线程,请查看异步读取.


Kev*_*bet 6

你看到100%CPU使用率的原因是你总是在做一些事情,这是你无休止的循环而没有延迟的结果.

基本语义是:

  1. 检查客户端是否已连接
  2. 轮询客户
  3. 检查数据是否可用
  4. 阅读数据
  5. 回到第1步

既然你处于这个循环中,那么无论它是什么,你总是会做一些事情.最简单的语义是在循环结束时执行Thread.sleep().这将帮助您,而无需进行任何更改.但是,你会引入任何睡眠时间的延迟,并且不是真正适合的方式(但可能适合你的情况).

正确的方法是在需要高性能服务器时学习异步套接字,或在连接1个或多个套接字时使用合适的低CPU.快速谷歌搜索可能是最好的学习,我不记得任何特别好的文章.异步IO的好处基本上是您只有在有事情要做时才会使用CPU时间.收到数据后,将调用您的方法来执行您必须执行的任何处理.


Mik*_*scu 5

这是因为您经常要求CPU为您做一些事情 - 即检查流上是否有可用的内容.

这是一个非常常见的模式,您需要学会妥善处理.它被称为异步IO,好消息是.NET框架提供了广泛的支持,使您可以轻松地完成所需的操作,而无需经常将CPU运行到100%.

最大的问题是你的代码在无限循环中运行,不断调用client.Client.Poll(0, SelectMode.SelectRead)哪个代码会立即回复.相反,你应该的框架时通知您一些有趣的事情发生,比如当有数据可从网络流中读取.而且你可以通过多种方式做到这一点.一种方法是使用NetowrkStream 的BeginRead方法.

以下是客户端应用程序的异步套接字编程示例.