使用委托时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%),所以很明显我做错了,但怎么会这样呢?

感谢

使用委托时CPU%过高

您只异步读取第一个字节,然后在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线程会有所帮助。