High CPU% when using delegate

I run the following code snippet that a delegate uses to return an asynchronous network stream:

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); } } } 

It works, but my processor is used through the roof (50% on Intel Core i3), so obviously I'm doing it wrong, but how is it?

thanks

+4
source share
3 answers

You read only the first bytes asynchronously, after which you end up in an endless loop with read operations with synchronization in your OnBeginRead method (which is the confusing name BTW). At the same time, these first bytes are discarded in your current code.

You need to process the data after EndRead (this is a function that returns the number of bytes that were read in the buffer in this async operation), and then start another async reading with BeginRead and return (there is no loop in asynchronous code!).

Edited to add a sample showing how async reading will work:

 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); } } 
+4
source

You are continuously moving through the main stream:

 while (true) { } 

This causes the processor core of this thread to remain at full capacity. Try to sleep to prevent unnecessary processor overflow:

 while (true) { Thread.Sleep(5000); } 
+1
source

Perhaps replace the processor rotation inefficiency at the bottom of the main method from

 while (true) { } 

to

 Console.ReadLine(); 

By the way, Lucero spot. You go into the infinte loop (in OnBeginRead) with a thread that calls the callback method. This seems wrong. Callbacks should be processed as soon as possible in order to process the calling thread. You usually retrieve data in a callback and send a signal to your stream to process the rest. Perhaps TPL will help here.

+1
source

Source: https://habr.com/ru/post/1392949/


All Articles