diff --git a/Terminal.Gui/Application.cs b/Terminal.Gui/Application.cs index f1000140d..52198afad 100644 --- a/Terminal.Gui/Application.cs +++ b/Terminal.Gui/Application.cs @@ -464,8 +464,8 @@ namespace Terminal.Gui { /// To make a stop execution, call . /// /// - /// Calling is equivalent to calling , followed by , - /// and then calling . + /// Calling is equivalent to calling , + /// followed by , and then calling . /// /// /// Alternatively, to have a program control the main loop and @@ -481,7 +481,7 @@ namespace Terminal.Gui { /// this method will exit. /// /// - /// The to run modally. + /// The to run as a modal. /// RELEASE builds only: Handler for any unhandled exceptions (resumes when returns true, rethrows when null). public static void Run (Toplevel view, Func errorHandler = null) { diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs index 2320e5458..e1f4cc06b 100644 --- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs @@ -1301,9 +1301,9 @@ internal class NetDriver : ConsoleDriver { /// This implementation is used for NetDriver. /// internal class NetMainLoop : IMainLoopDriver { - ManualResetEventSlim _keyReady = new ManualResetEventSlim (false); - ManualResetEventSlim _waitForProbe = new ManualResetEventSlim (false); - Queue _inputResult = new Queue (); + readonly ManualResetEventSlim _keyReady = new ManualResetEventSlim (false); + readonly ManualResetEventSlim _waitForProbe = new ManualResetEventSlim (false); + readonly Queue _inputResult = new Queue (); MainLoop _mainLoop; CancellationTokenSource _tokenSource = new CancellationTokenSource (); internal NetEvents _netEvents; @@ -1369,6 +1369,8 @@ internal class NetMainLoop : IMainLoopDriver { try { if (!_tokenSource.IsCancellationRequested) { + // Note: ManualResetEventSlim.Wait will wait indefinitely if the timeout is -1. The timeout is -1 when there + // are no timers, but there IS an idle handler waiting. _keyReady.Wait (waitTimeout, _tokenSource.Token); } } catch (OperationCanceledException) { diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index d2f9ae5b0..7f94c2081 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -1765,18 +1765,18 @@ internal class WindowsDriver : ConsoleDriver { /// This implementation is used for WindowsDriver. /// internal class WindowsMainLoop : IMainLoopDriver { - ManualResetEventSlim _eventReady = new ManualResetEventSlim (false); - ManualResetEventSlim _waitForProbe = new ManualResetEventSlim (false); - ManualResetEventSlim _winChange = new ManualResetEventSlim (false); + readonly ManualResetEventSlim _eventReady = new ManualResetEventSlim (false); + readonly ManualResetEventSlim _waitForProbe = new ManualResetEventSlim (false); + readonly ManualResetEventSlim _winChange = new ManualResetEventSlim (false); MainLoop _mainLoop; - ConsoleDriver _consoleDriver; - WindowsConsole _winConsole; + readonly ConsoleDriver _consoleDriver; + readonly WindowsConsole _winConsole; bool _winChanged; Size _windowSize; CancellationTokenSource _eventReadyTokenSource = new CancellationTokenSource (); // The records that we keep fetching - Queue _resultQueue = new Queue (); + readonly Queue _resultQueue = new Queue (); /// /// Invoked when a Key is pressed or released. @@ -1790,7 +1790,7 @@ internal class WindowsMainLoop : IMainLoopDriver { public WindowsMainLoop (ConsoleDriver consoleDriver = null) { - _consoleDriver = consoleDriver ?? throw new ArgumentNullException ("Console driver instance must be provided."); + _consoleDriver = consoleDriver ?? throw new ArgumentNullException (nameof(consoleDriver)); _winConsole = ((WindowsDriver)consoleDriver).WinConsole; } @@ -1851,6 +1851,8 @@ internal class WindowsMainLoop : IMainLoopDriver { try { if (!_eventReadyTokenSource.IsCancellationRequested) { + // Note: ManualResetEventSlim.Wait will wait indefinitely if the timeout is -1. The timeout is -1 when there + // are no timers, but there IS an idle handler waiting. _eventReady.Wait (waitTimeout, _eventReadyTokenSource.Token); } } catch (OperationCanceledException) { @@ -1874,7 +1876,7 @@ internal class WindowsMainLoop : IMainLoopDriver { { while (_resultQueue.Count > 0) { var inputRecords = _resultQueue.Dequeue (); - if (inputRecords != null && inputRecords.Length > 0) { + if (inputRecords is { Length: > 0 }) { var inputEvent = inputRecords [0]; ProcessInput?.Invoke (inputEvent); } diff --git a/Terminal.Gui/MainLoop.cs b/Terminal.Gui/MainLoop.cs index 6024de146..11038b033 100644 --- a/Terminal.Gui/MainLoop.cs +++ b/Terminal.Gui/MainLoop.cs @@ -226,7 +226,8 @@ namespace Terminal.Gui { /// /// Called from to check if there are any outstanding timers or idle handlers. /// - /// Returns the number of milliseconds remaining in the current timer (if any). + /// Returns the number of milliseconds remaining in the current timer (if any). Will be -1 if + /// there are no active timers. /// if there is a timer or idle handler active. public bool CheckTimersAndIdleHandlers (out int waitTimeout) { @@ -245,6 +246,9 @@ namespace Terminal.Gui { } return true; } + // ManualResetEventSlim.Wait, which is called by IMainLoopDriver.EventsPending, will wait indefinitely if + // the timeout is -1. + waitTimeout = -1; } // There are no timers set, check if there are any idle handlers diff --git a/Terminal.sln.DotSettings b/Terminal.sln.DotSettings index 4200301f6..88ef43749 100644 --- a/Terminal.sln.DotSettings +++ b/Terminal.sln.DotSettings @@ -113,6 +113,7 @@ <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="_" Suffix="" Style="AaBb" /> True Terminal.sln.DotSettings