<PackageReference Include="NUnit" Version="4.1.0" />

EventPump

public class EventPump : IDisposable
EventPump pulls events out of an EventQueue and sends them to a listener. It is used to send events back to the client without using the CallContext of the test runner thread.
using NUnit.Framework.Interfaces; using System; using System.Runtime.CompilerServices; using System.Threading; namespace NUnit.Framework.Internal.Execution { [System.Runtime.CompilerServices.NullableContext(2)] [System.Runtime.CompilerServices.Nullable(0)] public class EventPump : IDisposable { [System.Runtime.CompilerServices.Nullable(1)] private static readonly Logger Log = InternalTrace.GetLogger("EventPump"); [System.Runtime.CompilerServices.Nullable(1)] private readonly ITestListener _eventListener; [System.Runtime.CompilerServices.Nullable(1)] private readonly EventQueue _events; private Thread _pumpThread; private int _pumpState; public EventPumpState PumpState => (EventPumpState)_pumpState; public string Name { get; set; } [System.Runtime.CompilerServices.NullableContext(1)] public EventPump(ITestListener eventListener, EventQueue events) { _eventListener = eventListener; _events = events; } public void Dispose() { Stop(); } public void Start() { if (Interlocked.CompareExchange(ref _pumpState, 1, 0) == 0) { _pumpThread = new Thread(PumpThreadProc) { Name = "EventPumpThread" + Name, Priority = ThreadPriority.Highest }; _pumpThread.Start(); } } public void Stop() { if (Interlocked.CompareExchange(ref _pumpState, 2, 1) == 1) { _events.Stop(); _pumpThread?.Join(); } } private void PumpThreadProc() { Log.Debug("Starting EventPump"); try { while (true) { Event event = _events.Dequeue(PumpState == EventPumpState.Pumping); if (event == null) break; try { event.Send(_eventListener); } catch (Exception exception) { Log.Error("Exception in event handler {0}", ExceptionHelper.BuildStackTrace(exception)); } } Log.Debug("EventPump Terminating"); } catch (Exception exception2) { Log.Error("Exception in pump thread {0}", ExceptionHelper.BuildStackTrace(exception2)); } finally { _pumpState = 0; if (_events.Count > 0) Log.Error("Event pump thread exiting with {0} events remaining"); } } } }