使用委托时CPU%过高
本文关键字:CPU% 过高 | 更新日期: 2023-09-27 18:21:18
我正在运行以下代码,该代码使用委托返回异步网络流:
static void Main(string[] args)
{
NetworkStream myNetworkStream;
Socket socket;
IPEndPoint maxPort = new IPEndPoint(IPAddress.Parse("xxx.xxx.xxx.xxx"), xxxx);
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
socket.Connect(maxPort);
myNetworkStream = new NetworkStream(socket);
byte[] buffer = new byte[1024];
int offset = 0;
int count = 1024;
string Command = "LOGIN,,,xxxx'n";
ASCIIEncoding encoder = new ASCIIEncoding();
myNetworkStream.BeginRead(buffer, offset, count, new AsyncCallback(OnBeginRead), myNetworkStream);
myNetworkStream.Write(encoder.GetBytes(Command), 0, encoder.GetByteCount(Command));
while (true) { }
}
public static void OnBeginRead(IAsyncResult ar)
{
NetworkStream ns = (NetworkStream)ar.AsyncState;
int bufferSize = 1024;
byte[] received = new byte[bufferSize];
ns.EndRead(ar);
int read;
while (true)
{
if (ns.DataAvailable)
{
string result = String.Empty;
read = ns.Read(received, 0, bufferSize);
result += Encoding.ASCII.GetString(received);
received = new byte[bufferSize];
result = result.Replace(" ", "");
result = result.Replace("'0", "");
result = result.Replace("'r'n", ",");
Console.WriteLine(result);
}
}
}
它是有效的,但我的CPU使用率已经达到了极限(在英特尔酷睿i3上为50%),所以很明显我做错了,但怎么会这样呢?
感谢
您只异步读取第一个字节,然后在OnBeginRead
方法(这是一个令人困惑的名称BTW)中使用同步读取操作进入无限循环。同时,这些第一个字节在当前代码中被丢弃。
您需要处理EndRead
之后的数据(这是一个返回在该异步操作中向缓冲区读取了多少字节的函数),然后用BeginRead
开始另一次异步读取并返回(异步代码中没有循环!)。
编辑后添加了一个示例,显示异步读取的工作方式:
internal class StreamHelper {
private readonly NetworkStream stream;
private readonly byte[] buffer = new byte[1024];
public StreamHelper(Socket socket) {
stream = new NetworkStream(socket);
}
public NetworkStream Stream {
get {
return stream;
}
}
public byte[] Buffer {
get {
return buffer;
}
}
}
private static void Main(string[] args) {
IPEndPoint maxPort = new IPEndPoint(IPAddress.Parse("xxx.xxx.xxx.xxx"), 100);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
socket.Connect(maxPort);
StreamHelper helper = new StreamHelper(socket);
helper.Stream.BeginRead(helper.Buffer, 0, helper.Buffer.Length, StreamReadCallback, helper);
string Command = "LOGIN,,,xxxx'n";
byte[] bytes = Encoding.ASCII.GetBytes(Command);
// note: the write isn't async, but should maybe be converted as well
helper.Stream.Write(bytes, 0, bytes.Length);
Console.ReadLine(); // wait for a return key press
}
private static void StreamReadCallback(IAsyncResult ar) {
StreamHelper helper = (StreamHelper)ar.AsyncState;
// note: EndRead will throw an exception if something went wrong - you should deal with that
int bytesRead = helper.Stream.EndRead(ar);
if (bytesRead > 0) {
string charsRead = Encoding.ASCII.GetString(helper.Buffer, 0, bytesRead);
Console.Write(charsRead);
helper.Stream.BeginRead(helper.Buffer, 0, helper.Buffer.Length, StreamReadCallback, helper);
}
}
您正在主线程上连续循环:
while (true) { }
这会导致该线程的CPU内核始终处于满容量状态。尝试睡眠以防止线程不必要地占用CPU时间:
while (true) { Thread.Sleep(5000); }
也许可以从中取代在主方法底部旋转处理器的低效性
while (true) { }
至
Console.ReadLine();
顺便说一句,Lucero说得很对。你正在进入一个infinte循环(在OnBeginRead中),其中有一个调用回调方法的线程。这感觉不对。回调应该尽快处理,让调用线程继续处理。通常情况下,你会提取回调中的数据,并向自己的线程发送信号来处理其余的数据。也许TPL线程会有所帮助。