diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs
index 7d6ed0d69..1e02a03ae 100644
--- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs
@@ -113,7 +113,9 @@ namespace Terminal.Gui {
ConsoleDriver consoleDriver;
volatile ConsoleKeyInfo [] cki = null;
static volatile bool isEscSeq;
- bool stopTasks;
+
+ internal CancellationTokenSource TokenSource = new CancellationTokenSource ();
+
#if PROCESS_REQUEST
bool neededProcessRequest;
#endif
@@ -125,21 +127,13 @@ namespace Terminal.Gui {
throw new ArgumentNullException ("Console driver instance must be provided.");
}
this.consoleDriver = consoleDriver;
- Task.Run (ProcessInputResultQueue);
- Task.Run (CheckWinChange);
- }
-
- internal void StopTasks ()
- {
- stopTasks = true;
+ Task.Run (ProcessInputResultQueue, TokenSource.Token);
+ Task.Run (CheckWinChange, TokenSource.Token);
}
public InputResult? ReadConsoleInput ()
{
- while (true) {
- if (stopTasks) {
- return null;
- }
+ while (!TokenSource.IsCancellationRequested) {
waitForStart.Set ();
winChange.Set ();
@@ -154,11 +148,13 @@ namespace Terminal.Gui {
return inputResultQueue.Dequeue ();
}
}
+
+ return null;
}
void ProcessInputResultQueue ()
{
- while (true) {
+ while (!TokenSource.IsCancellationRequested) {
waitForStart.Wait ();
waitForStart.Reset ();
@@ -176,12 +172,19 @@ namespace Terminal.Gui {
ConsoleModifiers mod = 0;
ConsoleKeyInfo newConsoleKeyInfo = default;
- while (true) {
- ConsoleKeyInfo consoleKeyInfo;
+ while (!TokenSource.IsCancellationRequested) {
+ ConsoleKeyInfo consoleKeyInfo = default;
try {
- consoleKeyInfo = Console.ReadKey (true);
- } catch (InvalidOperationException ex) {
+ if (Console.KeyAvailable) {
+ consoleKeyInfo = Console.ReadKey (true);
+ } else {
+ Task.Delay (100, TokenSource.Token).Wait (TokenSource.Token);
+ if (Console.KeyAvailable) {
+ consoleKeyInfo = Console.ReadKey (true);
+ }
+ }
+ } catch (OperationCanceledException) {
return;
}
@@ -209,18 +212,19 @@ namespace Terminal.Gui {
}
break;
} else {
- GetConsoleInputType (consoleKeyInfo);
- break;
+ if (consoleKeyInfo != default) {
+ GetConsoleInputType (consoleKeyInfo);
+ break;
+ }
}
+
+ TokenSource.Token.ThrowIfCancellationRequested ();
}
}
void CheckWinChange ()
{
- while (true) {
- if (stopTasks) {
- return;
- }
+ while (!TokenSource.IsCancellationRequested) {
winChange.Wait ();
winChange.Reset ();
WaitWinChange ();
@@ -230,13 +234,16 @@ namespace Terminal.Gui {
void WaitWinChange ()
{
- while (true) {
- // Wait for a while then check if screen has changed sizes
- Task.Delay (500).Wait ();
+ while (!TokenSource.IsCancellationRequested) {
+ try {
+ // Wait for a while then check if screen has changed sizes
+ Task.Delay (500, TokenSource.Token).Wait (TokenSource.Token);
+
+ } catch (OperationCanceledException) {
- if (stopTasks) {
return;
}
+
int buffHeight, buffWidth;
if (((NetDriver)consoleDriver).IsWinPlatform) {
buffHeight = Math.Max (Console.BufferHeight, 0);
@@ -699,7 +706,7 @@ namespace Terminal.Gui {
public override void End ()
{
- mainLoop.netEvents.StopTasks ();
+ mainLoop.Dispose ();
if (IsWinPlatform) {
NetWinConsole.Cleanup ();
@@ -1455,7 +1462,7 @@ namespace Terminal.Gui {
///
/// This implementation is used for NetDriver.
///
- internal class NetMainLoop : IMainLoopDriver {
+ internal class NetMainLoop : IMainLoopDriver, IDisposable {
ManualResetEventSlim keyReady = new ManualResetEventSlim (false);
ManualResetEventSlim waitForProbe = new ManualResetEventSlim (false);
Queue inputResult = new Queue ();
@@ -1485,27 +1492,25 @@ namespace Terminal.Gui {
void NetInputHandler ()
{
- while (true) {
+ while (!tokenSource.IsCancellationRequested) {
waitForProbe.Wait ();
waitForProbe.Reset ();
if (inputResult.Count == 0) {
inputResult.Enqueue (netEvents.ReadConsoleInput ());
}
- try {
- while (inputResult.Peek () == null) {
- inputResult.Dequeue ();
- }
- if (inputResult.Count > 0) {
- keyReady.Set ();
- }
- } catch (InvalidOperationException) { }
+ while (inputResult.Count > 0 && inputResult.Peek () == null) {
+ inputResult.Dequeue ();
+ }
+ if (inputResult.Count > 0) {
+ keyReady.Set ();
+ }
}
}
void IMainLoopDriver.Setup (MainLoop mainLoop)
{
this.mainLoop = mainLoop;
- Task.Run (NetInputHandler);
+ Task.Run (NetInputHandler, tokenSource.Token);
}
void IMainLoopDriver.Wakeup ()
@@ -1535,8 +1540,7 @@ namespace Terminal.Gui {
return inputResult.Count > 0 || CheckTimers (wait, out _);
}
- tokenSource.Dispose ();
- tokenSource = new CancellationTokenSource ();
+ tokenSource.Token.ThrowIfCancellationRequested ();
return true;
}
@@ -1569,5 +1573,11 @@ namespace Terminal.Gui {
ProcessInput?.Invoke (inputResult.Dequeue ().Value);
}
}
+
+ public void Dispose ()
+ {
+ tokenSource.Cancel ();
+ netEvents.TokenSource.Cancel ();
+ }
}
}
\ No newline at end of file
diff --git a/Terminal.Gui/Core/Application.cs b/Terminal.Gui/Core/Application.cs
index 52343079b..9e981ce0d 100644
--- a/Terminal.Gui/Core/Application.cs
+++ b/Terminal.Gui/Core/Application.cs
@@ -1133,9 +1133,9 @@ namespace Terminal.Gui {
// BUGBUG: MdiTop is not cleared here, but it should be?
- MainLoop = null;
Driver?.End ();
Driver = null;
+ MainLoop = null;
Iteration = null;
RootMouseEvent = null;
RootKeyEvent = null;