Threading.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading;
  4. using System.Threading.Tasks;
  5. using Terminal.Gui;
  6. namespace UICatalog.Scenarios;
  7. [ScenarioMetadata ("Threading", "Demonstration of how to use threading in different ways")]
  8. [ScenarioCategory ("Threading")]
  9. public class Threading : Scenario
  10. {
  11. private readonly List<string> _log = [];
  12. private Action _action;
  13. private Button _btnActionCancel;
  14. private CancellationTokenSource _cancellationTokenSource;
  15. private EventHandler _handler;
  16. private ListView _itemsList;
  17. private Action _lambda;
  18. private ListView _logJob;
  19. private Action _sync;
  20. public override void Setup ()
  21. {
  22. _action = LoadData;
  23. _lambda = async () =>
  24. {
  25. _itemsList.Source = null;
  26. LogJob ("Loading task lambda");
  27. List<string> items = await LoadDataAsync ();
  28. LogJob ("Returning from task lambda");
  29. await _itemsList.SetSourceAsync (items);
  30. };
  31. _handler = async (s, e) =>
  32. {
  33. _itemsList.Source = null;
  34. LogJob ("Loading task handler");
  35. List<string> items = await LoadDataAsync ();
  36. LogJob ("Returning from task handler");
  37. await _itemsList.SetSourceAsync (items);
  38. };
  39. _sync = () =>
  40. {
  41. _itemsList.Source = null;
  42. LogJob ("Loading task synchronous");
  43. List<string> items =
  44. ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"];
  45. LogJob ("Returning from task synchronous");
  46. _itemsList.SetSource (items);
  47. };
  48. _btnActionCancel = new Button { X = 1, Y = 1, Text = "Cancelable Load Items" };
  49. _btnActionCancel.Accept += (s, e) => Application.Invoke (CallLoadItemsAsync);
  50. Win.Add (new Label { X = Pos.X (_btnActionCancel), Y = Pos.Y (_btnActionCancel) + 4, Text = "Data Items:" });
  51. _itemsList = new ListView
  52. {
  53. X = Pos.X (_btnActionCancel),
  54. Y = Pos.Y (_btnActionCancel) + 6,
  55. Width = 10,
  56. Height = 10,
  57. ColorScheme = Colors.ColorSchemes ["TopLevel"]
  58. };
  59. Win.Add (new Label { X = Pos.Right (_itemsList) + 10, Y = Pos.Y (_btnActionCancel) + 4, Text = "Task Logs:" });
  60. _logJob = new ListView
  61. {
  62. X = Pos.Right (_itemsList) + 10,
  63. Y = Pos.Y (_itemsList),
  64. Width = 50,
  65. Height = Dim.Fill (),
  66. ColorScheme = Colors.ColorSchemes ["TopLevel"],
  67. Source = new ListWrapper (_log)
  68. };
  69. var text = new TextField { X = 1, Y = 3, Width = 100, Text = "Type anything after press the button" };
  70. var btnAction = new Button { X = 80, Y = 10, Text = "Load Data Action" };
  71. btnAction.Accept += (s, e) => _action.Invoke ();
  72. var btnLambda = new Button { X = 80, Y = 12, Text = "Load Data Lambda" };
  73. btnLambda.Accept += (s, e) => _lambda.Invoke ();
  74. var btnHandler = new Button { X = 80, Y = 14, Text = "Load Data Handler" };
  75. btnHandler.Accept += (s, e) => _handler.Invoke (null, EventArgs.Empty);
  76. var btnSync = new Button { X = 80, Y = 16, Text = "Load Data Synchronous" };
  77. btnSync.Accept += (s, e) => _sync.Invoke ();
  78. var btnMethod = new Button { X = 80, Y = 18, Text = "Load Data Method" };
  79. btnMethod.Accept += async (s, e) => await MethodAsync ();
  80. var btnClearData = new Button { X = 80, Y = 20, Text = "Clear Data" };
  81. btnClearData.Accept += (s, e) =>
  82. {
  83. _itemsList.Source = null;
  84. LogJob ("Cleaning Data");
  85. };
  86. var btnQuit = new Button { X = 80, Y = 22, Text = "Quit" };
  87. btnQuit.Accept += (s, e) => Application.RequestStop ();
  88. Win.Add (
  89. _itemsList,
  90. _btnActionCancel,
  91. _logJob,
  92. text,
  93. btnAction,
  94. btnLambda,
  95. btnHandler,
  96. btnSync,
  97. btnMethod,
  98. btnClearData,
  99. btnQuit
  100. );
  101. void Top_Loaded (object sender, EventArgs args)
  102. {
  103. _btnActionCancel.SetFocus ();
  104. Top.Loaded -= Top_Loaded;
  105. }
  106. Top.Loaded += Top_Loaded;
  107. }
  108. private async void CallLoadItemsAsync ()
  109. {
  110. _cancellationTokenSource = new CancellationTokenSource ();
  111. _itemsList.Source = null;
  112. LogJob ("Clicked the button");
  113. if (_btnActionCancel.Text != "Cancel")
  114. {
  115. _btnActionCancel.Text = "Cancel";
  116. }
  117. else
  118. {
  119. _btnActionCancel.Text = "Cancelable Load Items";
  120. await _cancellationTokenSource.CancelAsync ();
  121. }
  122. try
  123. {
  124. if (_cancellationTokenSource.Token.IsCancellationRequested)
  125. {
  126. _cancellationTokenSource.Token.ThrowIfCancellationRequested ();
  127. }
  128. LogJob ($"Calling task Thread:{Thread.CurrentThread.ManagedThreadId} {DateTime.Now}");
  129. List<string> items = await Task.Run (LoadItemsAsync, _cancellationTokenSource.Token);
  130. if (!_cancellationTokenSource.IsCancellationRequested)
  131. {
  132. LogJob (
  133. $"Returned from task Thread:{Thread.CurrentThread.ManagedThreadId} {DateTime.Now}"
  134. );
  135. await _itemsList.SetSourceAsync (items);
  136. LogJob (
  137. $"Finished populate list view Thread:{Thread.CurrentThread.ManagedThreadId} {DateTime.Now}"
  138. );
  139. _btnActionCancel.Text = "Cancelable Load Items";
  140. }
  141. else
  142. {
  143. LogJob ("Task was canceled!");
  144. }
  145. }
  146. catch (OperationCanceledException ex)
  147. {
  148. LogJob (ex.Message);
  149. }
  150. }
  151. private async void LoadData ()
  152. {
  153. _itemsList.Source = null;
  154. LogJob ("Loading task");
  155. List<string> items = await LoadDataAsync ();
  156. LogJob ("Returning from task");
  157. await _itemsList.SetSourceAsync (items);
  158. }
  159. private async Task<List<string>> LoadDataAsync ()
  160. {
  161. _itemsList.Source = null;
  162. LogJob ("Starting delay");
  163. await Task.Delay (3000);
  164. LogJob ("Finished delay");
  165. return
  166. [
  167. "One",
  168. "Two",
  169. "Three",
  170. "Four",
  171. "Five",
  172. "Six",
  173. "Seven",
  174. "Eight",
  175. "Nine",
  176. "Ten",
  177. "Four",
  178. "Five",
  179. "Six",
  180. "Seven",
  181. "Eight",
  182. "Nine",
  183. "Ten"
  184. ];
  185. }
  186. private async Task<List<string>> LoadItemsAsync ()
  187. {
  188. // Do something that takes lot of times.
  189. LogJob ($"Starting delay Thread:{Thread.CurrentThread.ManagedThreadId} {DateTime.Now}");
  190. await Task.Delay (5000);
  191. LogJob ($"Finished delay Thread:{Thread.CurrentThread.ManagedThreadId} {DateTime.Now}");
  192. return ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"];
  193. }
  194. private void LogJob (string job)
  195. {
  196. _log.Add (job);
  197. _logJob.MoveDown ();
  198. }
  199. private async Task MethodAsync ()
  200. {
  201. _itemsList.Source = null;
  202. LogJob ("Loading task method");
  203. List<string> items = ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"];
  204. await Task.Delay (3000);
  205. LogJob ("Returning from task method");
  206. await _itemsList.SetSourceAsync (items);
  207. _itemsList.SetNeedsDisplay ();
  208. }
  209. }