c# - 使用委托(delegate)时 CPU 百分比高

标签 c# asynchronous delegates

我正在运行以下使用委托(delegate)返回异步网络流的代码:

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 使用率飙升(在 Intel Core 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);
    }
}

关于c# - 使用委托(delegate)时 CPU 百分比高,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9003912/

相关文章:

c# - 如何使用外键关联到不同表的 ID

c# - Nodatime BclDateTimeZone EqualsImpl 抛出 NotImplementedException

javascript - 如何从异步调用返回响应?

java - 如何使用 spring 配置异步和同步事件发布者

ios - 子类化 MKMapView 并使其成为 mapview 委托(delegate),同时仍然允许其他委托(delegate)

c# - Action 和 Func 参数不明确

swift - 通过 UITabBarController 移动到选定索引后 UIView 为零

c# - 如何在 C# 中指定非精确路径

c# - 我可以将 Windows (.bat) 文件放入 Visual Studio C# 项目的资源文件夹中吗?

javascript - 有没有办法像 alert() 函数那样在 JavaScript 中强制执行同步行为?