Files
Terminal.Gui/UICatalog/Scenarios/SingleBackgroundWorker.cs
usr c7942ae3bb Fix issue where the TestViewsDisposeCorrectly was not doing what it was supposed to do (#2964)
* add Disposal Test and fix an ssue where the CopyClipboard test was failing

* Update ViewDisposalTest.cs

* Update ViewDisposalTest.cs: Some Formatting, and adding code comments.

* Fix ViewDisposalTests (Wasn't working the way it was supposed to)

* update test

* update test

* update test

* try to fix as many conflicts as possible

* make test output prettier

* fix formatting

* Fix Subviews not being empty after disposing on all views.

* The fail cause was Application.Top not being disposed.

* Fix others containers that weren't being removed.

* Revert "The fail cause was Application.Top not being disposed."

This reverts commit 0c2183ed9e.

* Application.Top isn't null and need disposing.

* Fixes #2985. Application.RunState must be responsible for dispose the Toplevel property.

* Change the unit test with ans without Application.Shutdown method.

* Update ViewDisposeTests to actually check wether ALL views have been disposed (not just container)

* small additional check just to be safe

* Update ViewDisposalTest.cs: Formatting

* Update ViewDisposalTest.cs: Minor change to re-trigger Action

TestVKPacket is acting up again. Maybe the test is running async and is receiving scan codes from other instances?

---------

Co-authored-by: John Züchler <john.zuechler@eks-intec.de>
Co-authored-by: BDisp <bd.bdisp@gmail.com>
Co-authored-by: Tig <tig@users.noreply.github.com>
2023-11-15 09:22:22 -07:00

182 lines
4.9 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using Terminal.Gui;
namespace UICatalog.Scenarios {
[ScenarioMetadata (Name: "Single BackgroundWorker", Description: "A single BackgroundWorker threading opening another Toplevel")]
[ScenarioCategory ("Threading")]
[ScenarioCategory ("Top Level Windows")]
public class SingleBackgroundWorker : Scenario {
public override void Run ()
{
Application.Top.Dispose ();
Application.Run<MainApp> ();
System.Diagnostics.Debug.Assert (Application.Top == null);
}
public class MainApp : Toplevel {
private BackgroundWorker worker;
private List<string> log = new List<string> ();
private DateTime? startStaging;
private ListView listLog;
public MainApp ()
{
var menu = new MenuBar (new MenuBarItem [] {
new MenuBarItem ("_Options", new MenuItem [] {
new MenuItem ("_Run Worker", "", () => RunWorker(), null, null, Key.CtrlMask | Key.R),
null,
new MenuItem ("_Quit", "", () => Application.RequestStop(), null, null, Key.CtrlMask | Key.Q)
})
});
Add (menu);
var statusBar = new StatusBar (new [] {
new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Exit", () => Application.RequestStop()),
new StatusItem(Key.CtrlMask | Key.P, "~^R~ Run Worker", () => RunWorker())
});
Add (statusBar);
var top = new Toplevel ();
top.Add (new Label ("Worker Log") {
X = Pos.Center (),
Y = 0
});
listLog = new ListView (log) {
X = 0,
Y = 2,
Width = Dim.Fill (),
Height = Dim.Fill ()
};
top.Add (listLog);
Add (top);
}
private void RunWorker ()
{
worker = new BackgroundWorker () { WorkerSupportsCancellation = true };
var cancel = new Button ("Cancel Worker");
cancel.Clicked += () => {
if (worker == null) {
log.Add ($"Worker is not running at {DateTime.Now}!");
listLog.SetNeedsDisplay ();
return;
}
log.Add ($"Worker {startStaging}.{startStaging:fff} is canceling at {DateTime.Now}!");
listLog.SetNeedsDisplay ();
worker.CancelAsync ();
};
startStaging = DateTime.Now;
log.Add ($"Worker is started at {startStaging}.{startStaging:fff}");
listLog.SetNeedsDisplay ();
var md = new Dialog ($"Running Worker started at {startStaging}.{startStaging:fff}", cancel);
md.Add (new Label ("Wait for worker to finish...") {
X = Pos.Center (),
Y = Pos.Center ()
});
worker.DoWork += (s, e) => {
var stageResult = new List<string> ();
for (int i = 0; i < 500; i++) {
stageResult.Add ($"Worker {i} started at {DateTime.Now}");
e.Result = stageResult;
Thread.Sleep (1);
if (worker.CancellationPending) {
e.Cancel = true;
return;
}
}
};
worker.RunWorkerCompleted += (s, e) => {
if (md.IsCurrentTop) {
//Close the dialog
Application.RequestStop ();
}
if (e.Error != null) {
// Failed
log.Add ($"Exception occurred {e.Error.Message} on Worker {startStaging}.{startStaging:fff} at {DateTime.Now}");
listLog.SetNeedsDisplay ();
} else if (e.Cancelled) {
// Canceled
log.Add ($"Worker {startStaging}.{startStaging:fff} was canceled at {DateTime.Now}!");
listLog.SetNeedsDisplay ();
} else {
// Passed
log.Add ($"Worker {startStaging}.{startStaging:fff} was completed at {DateTime.Now}.");
listLog.SetNeedsDisplay ();
Application.Refresh ();
var builderUI = new StagingUIController (startStaging, e.Result as List<string>);
builderUI.Load ();
}
worker = null;
};
worker.RunWorkerAsync ();
Application.Run (md);
}
}
public class StagingUIController : Window {
Toplevel top;
public StagingUIController (DateTime? start, List<string> list)
{
top = new Toplevel (Application.Top.Frame);
top.KeyPress += (e) => {
// Prevents Ctrl+Q from closing this.
// Only Ctrl+C is allowed.
if (e.KeyEvent.Key == (Key.Q | Key.CtrlMask)) {
e.Handled = true;
}
};
bool Close ()
{
var n = MessageBox.Query (50, 7, "Close Window.", "Are you sure you want to close this window?", "Yes", "No");
return n == 0;
}
var menu = new MenuBar (new MenuBarItem [] {
new MenuBarItem ("_Stage", new MenuItem [] {
new MenuItem ("_Close", "", () => { if (Close()) { Application.RequestStop(); } }, null, null, Key.CtrlMask | Key.C)
})
});
top.Add (menu);
var statusBar = new StatusBar (new [] {
new StatusItem(Key.CtrlMask | Key.C, "~^C~ Close", () => { if (Close()) { Application.RequestStop(); } }),
});
top.Add (statusBar);
Title = $"Worker started at {start}.{start:fff}";
ColorScheme = Colors.Base;
Add (new ListView (list) {
X = 0,
Y = 0,
Width = Dim.Fill (),
Height = Dim.Fill ()
});
top.Add (this);
}
public void Load ()
{
Application.Run (top);
}
}
}
}