123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.ComponentModel;
- using System.Threading;
- using Terminal.Gui;
- namespace UICatalog.Scenarios;
- [ScenarioMetadata ("Single BackgroundWorker", "A single BackgroundWorker threading opening another Toplevel")]
- [ScenarioCategory ("Threading")]
- [ScenarioCategory ("Top Level Windows")]
- public class SingleBackgroundWorker : Scenario
- {
- public override void Init ()
- {
- Application.Run<MainApp> ();
- Application.Top.Dispose ();
- }
- public override void Run () { }
- public class MainApp : Toplevel
- {
- private readonly ListView _listLog;
- private readonly ObservableCollection<string> _log = [];
- private DateTime? _startStaging;
- private BackgroundWorker _worker;
- public MainApp ()
- {
- var menu = new MenuBar
- {
- Menus =
- [
- new MenuBarItem (
- "_Options",
- new MenuItem []
- {
- new (
- "_Run Worker",
- "",
- () => RunWorker (),
- null,
- null,
- KeyCode.CtrlMask | KeyCode.R
- ),
- null,
- new (
- "_Quit",
- "",
- () => Application.RequestStop (),
- null,
- null,
- KeyCode.CtrlMask | KeyCode.Q
- )
- }
- )
- ]
- };
- Add (menu);
- var statusBar = new StatusBar (
- new []
- {
- new StatusItem (
- Application.QuitKey,
- $"{Application.QuitKey} to Quit",
- () => Application.RequestStop ()
- ),
- new StatusItem (
- KeyCode.CtrlMask | KeyCode.P,
- "~^R~ Run Worker",
- () => RunWorker ()
- )
- }
- );
- Add (statusBar);
- var workerLogTop = new Toplevel () { Title = "Worker Log Top"};
- workerLogTop.Add (
- new Label { X = Pos.Center (), Y = 0, Text = "Worker Log" }
- );
- _listLog = new ListView
- {
- X = 0,
- Y = 2,
- Width = Dim.Fill (),
- Height = Dim.Fill (),
- Source = new ListWrapper<string> (_log)
- };
- workerLogTop.Add (_listLog);
- Add (workerLogTop);
- Title = "MainApp";
- }
- private void RunWorker ()
- {
- _worker = new BackgroundWorker { WorkerSupportsCancellation = true };
- var cancel = new Button { Text = "Cancel Worker" };
- cancel.Accept += (s, e) =>
- {
- 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
- {
- Title = $"Running Worker started at {_startStaging}.{_startStaging:fff}", Buttons = [cancel]
- };
- md.Add (
- new Label { X = Pos.Center (), Y = Pos.Center (), Text = "Wait for worker to finish..." }
- );
- _worker.DoWork += (s, e) =>
- {
- List<string> stageResult = new ();
- for (var 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 ObservableCollection<string>);
- var top = Application.Top;
- top.Visible = false;
- Application.Current.Visible = false;
- builderUI.Load ();
- builderUI.Dispose ();
- top.Visible = true;
- }
- _worker = null;
- };
- _worker.RunWorkerAsync ();
- Application.Run (md);
- md.Dispose ();
- }
- }
- public class StagingUIController : Window
- {
- private Toplevel _top;
- public StagingUIController (DateTime? start, ObservableCollection<string> list)
- {
- _top = new Toplevel
- {
- Title = "_top", Width = Dim.Fill (), Height = Dim.Fill ()
- };
- _top.KeyDown += (s, e) =>
- {
- // Prevents Ctrl+Q from closing this.
- // Only Ctrl+C is allowed.
- if (e == Application.QuitKey)
- {
- e.Handled = true;
- }
- };
- bool Close ()
- {
- int 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
- {
- Menus =
- [
- new MenuBarItem (
- "_Stage",
- new MenuItem []
- {
- new (
- "_Close",
- "",
- () =>
- {
- if (Close ())
- {
- Application.RequestStop ();
- }
- },
- null,
- null,
- KeyCode.CtrlMask | KeyCode.C
- )
- }
- )
- ]
- };
- _top.Add (menu);
- var statusBar = new StatusBar (
- new []
- {
- new StatusItem (
- KeyCode.CtrlMask | KeyCode.C,
- "~^C~ Close",
- () =>
- {
- if (Close ())
- {
- Application.RequestStop ();
- }
- }
- )
- }
- );
- _top.Add (statusBar);
- Title = $"Worker started at {start}.{start:fff}";
- ColorScheme = Colors.ColorSchemes ["Base"];
- Add (
- new ListView
- {
- X = 0,
- Y = 0,
- Width = Dim.Fill (),
- Height = Dim.Fill (),
- Source = new ListWrapper<string> (list)
- }
- );
- _top.Add (this);
- }
- public void Load () {
- Application.Run (_top);
- _top.Dispose ();
- _top = null;
- }
- ///// <inheritdoc />
- //protected override void Dispose (bool disposing)
- //{
- // _top?.Dispose ();
- // _top = null;
- // base.Dispose (disposing);
- //}
- }
- }
|