mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
Remove InvalidOperationException and use Task.Delay with CancellationTokenSource.
This commit is contained in:
@@ -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 {
|
||||
/// <remarks>
|
||||
/// This implementation is used for NetDriver.
|
||||
/// </remarks>
|
||||
internal class NetMainLoop : IMainLoopDriver {
|
||||
internal class NetMainLoop : IMainLoopDriver, IDisposable {
|
||||
ManualResetEventSlim keyReady = new ManualResetEventSlim (false);
|
||||
ManualResetEventSlim waitForProbe = new ManualResetEventSlim (false);
|
||||
Queue<NetEvents.InputResult?> inputResult = new Queue<NetEvents.InputResult?> ();
|
||||
@@ -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 ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user