简体   繁体   English

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

[英]Reading on a NetworkStream = 100% CPU usage

I am reading from a NetworkStream that is in a while loop. 我正在从一个在while循环中的NetworkStream中读取。 The issue is I am seeing 100% CPU usage. 问题是我看到100%的CPU使用率。 Is there any way to stop this from happening? 有没有办法阻止这种情况发生?

Here is what I have so far: 这是我到目前为止:

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

... Code continues... ......代码继续......

ReadStringFromClient code: 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;

    }

Your code contains a lot of... noise. 你的代码包含很多......噪音。 You Ain't Gonna Need It. 你不需要它。

The reason for 100% CPU load is that you're spin-waiting for data to become available. 100%CPU负载的原因是您在等待数据变得可用。 You don't need to do that. 你不需要这样做。 Read will block until data is available. Read将阻塞,直到数据可用。 You also don't need to recreate the NetworkStream for each chunk of data to receive. 您也不需要为每个要接收的数据块重新创建NetworkStream

Your code can be much simplified if you'd use a StreamReader : 如果您使用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);
    }
}

Read block until data becomes available. Read块直到数据可用。 The code loops while the connection is alive. 连接处于活动状态时代码循环。 You can simplify the code even further if you use ReadLine instead of reading into a char buffer. 如果使用ReadLine而不是读入char缓冲区,则可以进一步简化代码。

If you don't want to block your thread until data becomes available, have a look at asynchronous reading. 如果您不希望在数据可用之前阻塞线程,请查看异步读取。

The reason you are seeing 100% CPU usage, is that you're always doing something, which is a result of your endless while loop with no delays. 你看到100%CPU使用率的原因是你总是在做一些事情,这是你无休止的循环而没有延迟的结果。

The basic semantics are: 基本语义是:

  1. Check if client is connected 检查客户端是否已连接
  2. Poll the client 轮询客户
  3. Check if data is available 检查数据是否可用
  4. Read the data 阅读数据
  5. Go back to step 1 回到第1步

Since you're in this loop, you're always doing something, whatever it is. 既然你处于这个循环中,那么无论它是什么,你总是会做一些事情。 The easiest semantic is to do a Thread.sleep() at the end of your loop. 最简单的语义是在循环结束时执行Thread.sleep()。 This will help you without having to make many changes. 这将帮助您,而无需进行任何更改。 However, you will introduce a delay of whatever that sleep time is, and isn't really a proper way (but may suit your situation). 但是,你会引入任何睡眠时间的延迟,并且不是真正适合的方式(但可能适合你的情况)。

The proper method is to learn about asynchronous sockets if you want a high performance server, or something that uses suitable low CPU when 1 or more sockets are connected. 正确的方法是在需要高性能服务器时学习异步套接字,或在连接1个或多个套接字时使用合适的低CPU。 Doing a quick Google search is probably best to learn, I don't recall any particularly good articles off hand. 快速谷歌搜索可能是最好的学习,我不记得任何特别好的文章。 The benefit of Asynchronous IO is basically that you will only use CPU time when you have something to do. 异步IO的好处基本上是您只有在有事情要做时才会使用CPU时间。 When data is received, your method will be called to do whatever processing you have to do. 收到数据后,将调用您的方法来执行您必须执行的任何处理。

This is because you are constantly asking the CPU to do something for you - namely, to check if there is anything available on the stream. 这是因为您经常要求CPU为您做一些事情 - 即检查流上是否有可用的内容。

This is a pretty common pattern that you need to learn to deal with appropriately. 这是一个非常常见的模式,您需要学会妥善处理。 It is called asynchronous IO and the good news is that the .NET framework has extensive support to make it easy for you to accomplish what you want without running the CPU to 100% constantly. 它被称为异步IO,好消息是.NET框架提供了广泛的支持,使您可以轻松地完成所需的操作,而无需经常将CPU运行到100%。

The big problem is that your code is running in an endless loop, constantly calling client.Client.Poll(0, SelectMode.SelectRead) which will return immediately with an answer. 最大的问题是你的代码在无限循环中运行,不断调用client.Client.Poll(0, SelectMode.SelectRead) ,它将立即返回一个答案。 Instead, you should ask the framework to notify you when something interesting happens, such as when there's data available to read from the network stream. 相反,您应该要求框架在发生有趣事情时通知您,例如何时可以从网络流中读取数据。 And there's more than a handful of ways you can do that. 而且你可以通过多种方式做到这一点。 One way is to use the BeginRead method of the NetowrkStream. 一种方法是使用NetowrkStream的BeginRead方法。

Here's an example of asynchronous sockets programming example for a client application. 以下是客户端应用程序的异步套接字编程示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM