CPU使用问题
本文关键字:问题 CPU | 更新日期: 2023-09-27 18:05:43
我有一个网络项目,里面没有定时器。只是一个tcpclient,它连接到服务器并侦听从网络接收任何数据。
TcpClient _TcpClient = new TcpClient(_IpAddress, _Port);
_ConnectThread = new Thread(new ThreadStart(ConnectToServer));
_ConnectThread.IsBackground = true;
_ConnectThread.Start();
private void ConnectToServer()
{
try
{
NetworkStream _NetworkStream = _TcpClient.GetStream();
byte[] _RecievedPack = new byte[1024 * 1000];
string _Message = string.Empty;
int _BytesRead;
int _Length;
while (_Flage)
{
_BytesRead = _NetworkStream.Read(_RecievedPack, 0, _RecievedPack.Length);
_Length = BitConverter.ToInt32(_RecievedPack, 0);
_Message = UTF8Encoding.UTF8.GetString(_RecievedPack, 4, _Length);
if (_BytesRead != 0)
{
//call a function to manage the data
_NetworkStream.Flush();
}
}
}
catch (Exception exp)
{
// call a function to alarm that connection is false
}
}
但是过了一段时间,我的应用程序的cpu使用率上升了(90%,85%,…)。即使没有数据接收。
谁能给我一些关于CPU使用的建议?我脑子一片空白。我不知道我应该检查项目的哪一部分!谁能给我一些关于CPU使用的建议
你应该考虑检查应用程序中的循环,比如while
循环,如果你花了很多时间等待某个条件变为真,那么它会占用很多CPU时间。例如
while (true)
{}
或
while (_Flag)
{
//do something
}
如果while内执行的代码是同步的,那么线程将会消耗大量的CPU周期。为了解决这个问题,你可以在不同的线程中执行while内的代码,因此它将是异步的,然后使用ManualResetEvent
或AutoResetEvent
在操作执行时报告,另一件要提到的是考虑使用System.Threading.Thread.Sleep
方法使线程进入睡眠状态,并给cpu时间执行其他线程,例如:
while(_Flag)
{
//do something
Thread.Sleep(100);//Blocks the current thread for 100 milliseconds
}
你的代码有几个问题…最重要的是:
- 使用异步方法(
BeginRead
等),不要阻塞方法,不要创建自己的线程。线程是"昂贵的"资源,因此在线程中使用阻塞调用是对资源的浪费。使用异步调用可以让操作系统在事件(例如接收到的数据)发生时回调您,因此不需要单独的线程(回调与池线程一起运行)。注意Read
可能只返回几个字节,它不需要填充_ReceivedPack
缓冲区。理论上,它可能只接收一到两个字节——甚至不足以调用ToInt32
!
CPU使用率峰值,因为您有一个while循环,如果它没有从网络接收任何内容,则它不做任何事情。在它的末尾添加Thread.Sleep(),如果没有接收到数据,那么您的CPU使用将是正常的。
接受Lucero给你的建议
我怀疑当while
循环仍在运行时,连接的另一端已关闭,在这种情况下,您将反复从网络流中读取零字节(标记连接已关闭;看到NetworkStream。请在MSDN上阅读
由于NetworkStream.Read
将立即返回(根据MSDN),您将被困在一个紧凑的while循环中,这将消耗大量处理器时间。尝试添加Thread.Sleep()或在循环中检测"零读"。理想情况下,您也应该通过终止连接来处理0字节的读取。
while (_Flage)
{
_BytesRead = _NetworkStream.Read(_RecievedPack, 0, _RecievedPack.Length);
_Length = BitConverter.ToInt32(_RecievedPack, 0);
_Message = UTF8Encoding.UTF8.GetString(_RecievedPack, 4, _Length);
if (_BytesRead != 0)
{
//call a function to manage the data
_NetworkStream.Flush();
}
}
您是否附加了一个调试器并逐步检查代码以查看它是否按照您期望的方式运行?
或者,如果您有一个可用的分析工具(比如ANTs),那么这将帮助您查看您的应用程序中哪些地方花费了时间。