Browse Source

Fix high CPU load #708

InvictusMB 5 years ago
parent
commit
129f6403d8

+ 14 - 21
Terminal.Gui/ConsoleDrivers/CursesDriver/UnixMainLoop.cs

@@ -168,45 +168,38 @@ namespace Terminal.Gui {
 
 		bool IMainLoopDriver.EventsPending (bool wait)
 		{
-			int pollTimeout = 0;
-			int n;
-
-			if (CkeckTimeout (wait, ref pollTimeout))
+			if (CheckTimers (wait, out var pollTimeout)) {
 				return true;
+			}
 
 			UpdatePollMap ();
 
-			while (true) {
-				n = poll (pollmap, (uint)pollmap.Length, 0);
-				if (pollmap != null) {
-					break;
-				}
-				if (mainLoop.idleHandlers.Count > 0 || CkeckTimeout (wait, ref pollTimeout)) {
-					return true;
-				}
-			}
-			int ic;
-			lock (mainLoop.idleHandlers)
-				ic = mainLoop.idleHandlers.Count;
-			return n > 0 || mainLoop.timeouts.Count > 0 && ((mainLoop.timeouts.Keys [0] - DateTime.UtcNow.Ticks) < 0) || ic > 0;
+			var n = poll (pollmap, (uint)pollmap.Length, pollTimeout);
+			
+			return n > 0 || CheckTimers (wait, out pollTimeout);
 		}
 
-		bool CkeckTimeout (bool wait, ref int pollTimeout)
+		bool CheckTimers (bool wait, out int pollTimeout)
 		{
 			long now = DateTime.UtcNow.Ticks;
 
 			if (mainLoop.timeouts.Count > 0) {
 				pollTimeout = (int)((mainLoop.timeouts.Keys [0] - now) / TimeSpan.TicksPerMillisecond);
-				if (pollTimeout < 0)
+				if (pollTimeout < 0) {
 					return true;
-
+				}
 			} else
 				pollTimeout = -1;
 
 			if (!wait)
 				pollTimeout = 0;
 
-			return false;
+			int ic;
+			lock (mainLoop.idleHandlers) {
+				ic = mainLoop.idleHandlers.Count;
+			}
+
+			return ic > 0;
 		}
 
 		void IMainLoopDriver.MainIteration ()

+ 14 - 16
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -615,24 +615,16 @@ namespace Terminal.Gui {
 
 		bool IMainLoopDriver.EventsPending (bool wait)
 		{
-			int waitTimeout = 0;
-
-			if (CkeckTimeout (wait, ref waitTimeout))
+			if (CheckTimers (wait, out var waitTimeout)) {
 				return true;
+			}
 
 			result = null;
 			waitForProbe.Set ();
 
 			try {
-				while (result == null) {
-					if (!tokenSource.IsCancellationRequested)
-						eventReady.Wait (0, tokenSource.Token);
-					if (result != null) {
-						break;
-					}
-					if (mainLoop.idleHandlers.Count > 0 || CkeckTimeout (wait, ref waitTimeout)) {
-						return true;
-					}
+				if (!tokenSource.IsCancellationRequested) {
+					eventReady.Wait (waitTimeout, tokenSource.Token);
 				}
 			} catch (OperationCanceledException) {
 				return true;
@@ -640,15 +632,16 @@ namespace Terminal.Gui {
 				eventReady.Reset ();
 			}
 
-			if (!tokenSource.IsCancellationRequested)
-				return result != null;
+			if (!tokenSource.IsCancellationRequested) {
+				return result != null || CheckTimers (wait, out waitTimeout);
+			}
 
 			tokenSource.Dispose ();
 			tokenSource = new CancellationTokenSource ();
 			return true;
 		}
 
-		bool CkeckTimeout (bool wait, ref int waitTimeout)
+		bool CheckTimers (bool wait, out int waitTimeout)
 		{
 			long now = DateTime.UtcNow.Ticks;
 
@@ -663,7 +656,12 @@ namespace Terminal.Gui {
 			if (!wait)
 				waitTimeout = 0;
 
-			return false;
+			int ic;
+			lock (mainLoop.idleHandlers) {
+				ic = mainLoop.idleHandlers.Count;
+			}
+
+			return ic > 0;
 		}
 
 		Action<KeyEvent> keyHandler;

+ 3 - 1
Terminal.Gui/Core/MainLoop.cs

@@ -95,9 +95,11 @@ namespace Terminal.Gui {
 		/// <param name="idleHandler">Token that can be used to remove the idle handler with <see cref="RemoveIdle(Func{bool})"/> .</param>
 		public Func<bool> AddIdle (Func<bool> idleHandler)
 		{
-			lock (idleHandlers)
+			lock (idleHandlers) {
 				idleHandlers.Add (idleHandler);
+			}
 
+			Driver.Wakeup ();
 			return idleHandler;
 		}