diff --git a/src/Particular.PlatformSample/AppLauncher.cs b/src/Particular.PlatformSample/AppLauncher.cs index 692907e..20a7593 100644 --- a/src/Particular.PlatformSample/AppLauncher.cs +++ b/src/Particular.PlatformSample/AppLauncher.cs @@ -17,7 +17,7 @@ sealed class AppLauncher(bool showPlatformToolConsoleOutput) : IAsyncDisposable readonly Stack> cleanupActions = new(); readonly List platformTools = []; - public sealed record PlatformTool(string Name, Process Process, StringBuilder ErrorOutput); + public sealed record PlatformTool(string Name, Process Process, BoundedOutput ErrorOutput); public void StopProcesses() { @@ -215,7 +215,7 @@ void StartProcess(string name, string assemblyPath, Dictionary e } var process = Process.Start(startInfo); - var tool = new PlatformTool(name, process, new StringBuilder()); + var tool = new PlatformTool(name, process, new BoundedOutput()); // without this in certain occasions the start takes waaaaay longer! if (hideConsoleOutput) diff --git a/src/Particular.PlatformSample/BoundedOutput.cs b/src/Particular.PlatformSample/BoundedOutput.cs new file mode 100644 index 0000000..aca80c6 --- /dev/null +++ b/src/Particular.PlatformSample/BoundedOutput.cs @@ -0,0 +1,46 @@ +namespace Particular +{ + using System; + using System.Text; + + sealed class BoundedOutput + { + const int MaximumLength = 8192; + readonly StringBuilder output = new(MaximumLength); + + public void AppendLine(string line) + { + lock (output) + { + Append(line.AsSpan()); + Append(Environment.NewLine.AsSpan()); + } + } + + void Append(ReadOnlySpan text) + { + if (text.Length >= MaximumLength) + { + output.Clear(); + output.Append(text[^MaximumLength..]); + return; + } + + var excess = output.Length + text.Length - MaximumLength; + if (excess > 0) + { + output.Remove(0, excess); + } + + output.Append(text); + } + + public override string ToString() + { + lock (output) + { + return output.ToString(); + } + } + } +}