public Task TailAsync()

in sources/Google.Solutions.IapDesktop.Extensions.Management/ToolWindows/SerialOutput/SerialOutputModel.cs [93:158]


        public Task TailAsync(Action<string> newOutputFunc, CancellationToken token)
        {
            return Task.Run(async () =>
            {
                ApplicationTraceSource.Log.TraceVerbose("Start polling serial output");

                var exceptionCaught = false;
                while (!exceptionCaught)
                {
                    //
                    // Check if we can continue to tail.
                    //
                    if (token.IsCancellationRequested)
                    {
                        ApplicationTraceSource.Log.TraceVerbose("Stop polling serial output");
                        break;
                    }

                    string? newOutput;
                    try
                    {
                        ApplicationTraceSource.Log.TraceVerbose("Polling serial output...");
                        newOutput = await ReadAndBufferAsync(token).ConfigureAwait(false);
                    }
                    catch (TokenResponseException e)
                    {
                        newOutput = "Reading from serial port failed - session timed out " +
                            $"({e.Error.ErrorDescription})";
                        exceptionCaught = true;
                    }
                    catch (Exception e) when (e.IsCancellation())
                    {
                        //
                        // This is deliberate, so do not emit anything to output.
                        //
                        newOutput = null;
                    }
                    catch (Exception e)
                    {
                        newOutput = $"Reading from serial port failed: {e.Unwrap().Message}";
                        exceptionCaught = true;
                    }

                    //
                    // By the time we read the data, the form might have begun closing. In this
                    // case, updating the UI would cause an exception.
                    //
                    if (!token.IsCancellationRequested && newOutput != null && !string.IsNullOrEmpty(newOutput))
                    {
                        newOutputFunc(newOutput);
                    }

                    try
                    {
                        await Task.Delay(TimeSpan.FromSeconds(1), token).ConfigureAwait(false);
                    }
                    catch (TaskCanceledException)
                    {
                        //
                        // Do not let the exception escape, instead handle the cancellation
                        // in the next iteration.
                        //
                    }
                }
            });
        }