microsoft / dotnet

This repo is the official home of .NET on GitHub. It's a great starting point to find many .NET OSS projects from Microsoft and the community, including many that are part of the .NET Foundation.
https://devblogs.microsoft.com/dotnet/
MIT License
14.43k stars 2.21k forks source link

Process.StandardOutput.ReadAsync read data super slowly #1448

Closed vivek4434 closed 1 month ago

vivek4434 commented 1 month ago

I am trying to spin up ssh.exe as sub-process to interact with network device. I have to use ReadAsync API as i need to read complete data (irrespective of the fact if there is a newline or not). I am observing ReadAsync is responding super slow (compared to when i try to manually run ssh.exe). I have a waittime for 20ms to ensure data is available for read./ Below is my source code:

        private async Task GetIncomingBuffer()
        {
            ushort noDataAvailableAttempt = 0;
            try
            {
                char[] window = new char[1024];
                StringBuilder buf = new StringBuilder();
                bool pendingRead = true;
                while (!cancellationTokenSource.Token.IsCancellationRequested)
                {
                    var len = await process.StandardOutput.ReadAsync(window, 0, 1024).ConfigureAwait(false);

                    if (len > 0)
                    {
                        // Resetting counter.
                        noDataAvailableAttempt = 0;
                        for (int i = 0; i < len; i++)
                        {
                            buf.Append(window[i]);
                            if (window[i] == '\n' || window[i] == '\r')
                            {
                                this.incoming.Enqueue(buf.ToString());
                                buf.Clear();
                                pendingRead = false;
                                continue;
                            }

                            pendingRead = true;
                        }

                        if (pendingRead)
                        {
                            // last line do not have \n or \r so explicitly add it.
                            this.incoming.Enqueue(buf.ToString());
                            buf.Clear();
                            pendingRead = false;
                        }
                    }
                    else
                    {
                        noDataAvailableAttempt++;
                        if (noDataAvailableAttempt % noDataReadLogFrequency == 0)
                        {
                            this.logger.LogInfo("No data availabe for read...");
                            noDataAvailableAttempt = 0;
                        }
                    }

                    await Task.Delay(20).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                this.logger.LogWarning($"Error in GetIncomingBuffer: {ex.Message}");
            }
        }