![](/img/trans.png)
[英]NetworkStream Receive, how to processing data without using 100% CPU?
[英]Reading on a NetworkStream = 100% 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);
}
}
......代码继续......
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;
}
你的代码包含很多......噪音。 你不需要它。
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);
}
}
Read
块直到数据可用。 连接处于活动状态时代码循环。 如果使用ReadLine而不是读入char缓冲区,则可以进一步简化代码。
如果您不希望在数据可用之前阻塞线程,请查看异步读取。
你看到100%CPU使用率的原因是你总是在做一些事情,这是你无休止的循环而没有延迟的结果。
基本语义是:
既然你处于这个循环中,那么无论它是什么,你总是会做一些事情。 最简单的语义是在循环结束时执行Thread.sleep()。 这将帮助您,而无需进行任何更改。 但是,你会引入任何睡眠时间的延迟,并且不是真正适合的方式(但可能适合你的情况)。
正确的方法是在需要高性能服务器时学习异步套接字,或在连接1个或多个套接字时使用合适的低CPU。 快速谷歌搜索可能是最好的学习,我不记得任何特别好的文章。 异步IO的好处基本上是您只有在有事情要做时才会使用CPU时间。 收到数据后,将调用您的方法来执行您必须执行的任何处理。
这是因为您经常要求CPU为您做一些事情 - 即检查流上是否有可用的内容。
这是一个非常常见的模式,您需要学会妥善处理。 它被称为异步IO,好消息是.NET框架提供了广泛的支持,使您可以轻松地完成所需的操作,而无需经常将CPU运行到100%。
最大的问题是你的代码在无限循环中运行,不断调用client.Client.Poll(0, SelectMode.SelectRead)
,它将立即返回一个答案。 相反,您应该要求框架在发生有趣事情时通知您,例如何时可以从网络流中读取数据。 而且你可以通过多种方式做到这一点。 一种方法是使用NetowrkStream的BeginRead方法。
以下是客户端应用程序的异步套接字编程示例 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.