diff --git a/src/DiffEngineViewer.Tests/ModuleInitializer.cs b/src/DiffEngineViewer.Tests/ModuleInitializer.cs index 1dd21197..e9e334d1 100644 --- a/src/DiffEngineViewer.Tests/ModuleInitializer.cs +++ b/src/DiffEngineViewer.Tests/ModuleInitializer.cs @@ -11,5 +11,29 @@ public static void Initialize() // Before anything can touch DiffTools, which resolves and caches on first use. Only points // the resolver at the local build; nothing here launches anything. ManualViewer.Register(); + RaiseThreadPoolFloor(); + } + + /// + /// The socket tests need two pool threads per exchange, and a CI runner starts with about four + /// in total. + /// + /// drives the real ViewerClient, whose send is synchronous, + /// so a test blocks a pool thread for the whole exchange while the server needs threads of its + /// own to accept the connection and answer it. Run enough of those at once on a four core + /// runner and the answer waits on the pool's hill climb, which adds roughly one thread a + /// second, past the client's three second timeout. That surfaced as an intermittent "No + /// response for Inline", on a different platform and a different test each run. + /// + /// + /// Raising the floor removes the scarcity rather than the blocking. The blocking is real, but + /// it belongs to the client the tray and an attached viewer actually use, and no process runs + /// dozens of those at once — a test host is the only thing that does. + /// + /// + static void RaiseThreadPoolFloor() + { + ThreadPool.GetMinThreads(out var workers, out var completionPorts); + ThreadPool.SetMinThreads(Math.Max(workers, 32), completionPorts); } }