2
0

Threading.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. using System;
  2. using System.Collections.ObjectModel;
  3. using System.Threading;
  4. using System.Threading.Tasks;
  5. namespace UICatalog.Scenarios;
  6. [ScenarioMetadata ("Threading", "Demonstration of how to use threading in different ways")]
  7. [ScenarioCategory ("Threading")]
  8. public class Threading : Scenario
  9. {
  10. private readonly ObservableCollection<string> _log = [];
  11. private Action _action;
  12. private Button _btnActionCancel;
  13. private CancellationTokenSource _cancellationTokenSource;
  14. private EventHandler _handler;
  15. private ListView _itemsList;
  16. private Action _lambda;
  17. private ListView _logJob;
  18. private Action _sync;
  19. private LogarithmicTimeout _logarithmicTimeout;
  20. private NumericUpDown _numberLog;
  21. private Button _btnLogarithmic;
  22. private object _timeoutObj;
  23. private SmoothAcceleratingTimeout _smoothTimeout;
  24. private NumericUpDown _numberSmooth;
  25. private Button _btnSmooth;
  26. private object _timeoutObjSmooth;
  27. public override void Main ()
  28. {
  29. Application.Init ();
  30. var win = new Window { Title = GetQuitKeyAndName () };
  31. _action = LoadData;
  32. _lambda = async () =>
  33. {
  34. _itemsList.Source = null;
  35. LogJob ("Loading task lambda");
  36. ObservableCollection<string> items = await LoadDataAsync ();
  37. LogJob ("Returning from task lambda");
  38. await _itemsList.SetSourceAsync (items);
  39. };
  40. _handler = async (s, e) =>
  41. {
  42. _itemsList.Source = null;
  43. LogJob ("Loading task handler");
  44. ObservableCollection<string> items = await LoadDataAsync ();
  45. LogJob ("Returning from task handler");
  46. await _itemsList.SetSourceAsync (items);
  47. };
  48. _sync = () =>
  49. {
  50. _itemsList.Source = null;
  51. LogJob ("Loading task synchronous");
  52. ObservableCollection<string> items =
  53. ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"];
  54. LogJob ("Returning from task synchronous");
  55. _itemsList.SetSource (items);
  56. };
  57. _btnActionCancel = new Button { X = 1, Y = 1, Text = "Cancelable Load Items" };
  58. _btnActionCancel.Accepting += (s, e) => Application.Invoke (CallLoadItemsAsync);
  59. win.Add (new Label { X = Pos.X (_btnActionCancel), Y = Pos.Y (_btnActionCancel) + 4, Text = "Data Items:" });
  60. _itemsList = new ListView
  61. {
  62. X = Pos.X (_btnActionCancel),
  63. Y = Pos.Y (_btnActionCancel) + 6,
  64. Width = 10,
  65. Height = 10,
  66. SchemeName = "Runnable"
  67. };
  68. win.Add (new Label { X = Pos.Right (_itemsList) + 10, Y = Pos.Y (_btnActionCancel) + 4, Text = "Task Logs:" });
  69. _logJob = new ListView
  70. {
  71. X = Pos.Right (_itemsList) + 10,
  72. Y = Pos.Y (_itemsList),
  73. Width = 50,
  74. Height = Dim.Fill (),
  75. SchemeName = "Runnable",
  76. Source = new ListWrapper<string> (_log)
  77. };
  78. var text = new TextField { X = 1, Y = 3, Width = 100, Text = "Type anything after press the button" };
  79. _btnLogarithmic = new Button ()
  80. {
  81. X = 50,
  82. Y = 4,
  83. Text = "Start Log Counter"
  84. };
  85. _btnLogarithmic.Accepting += StartStopLogTimeout;
  86. _numberLog = new NumericUpDown ()
  87. {
  88. X = Pos.Right (_btnLogarithmic),
  89. Y = 4,
  90. };
  91. _btnSmooth = new Button ()
  92. {
  93. X = Pos.Right (_numberLog),
  94. Y = 4,
  95. Text = "Start Smooth Counter"
  96. };
  97. _btnSmooth.Accepting += StartStopSmoothTimeout;
  98. _numberSmooth = new NumericUpDown ()
  99. {
  100. X = Pos.Right (_btnSmooth),
  101. Y = 4,
  102. };
  103. var btnAction = new Button { X = 80, Y = 10, Text = "Load Data Action" };
  104. btnAction.Accepting += (s, e) => _action.Invoke ();
  105. var btnLambda = new Button { X = 80, Y = 12, Text = "Load Data Lambda" };
  106. btnLambda.Accepting += (s, e) => _lambda.Invoke ();
  107. var btnHandler = new Button { X = 80, Y = 14, Text = "Load Data Handler" };
  108. btnHandler.Accepting += (s, e) => _handler.Invoke (null, EventArgs.Empty);
  109. var btnSync = new Button { X = 80, Y = 16, Text = "Load Data Synchronous" };
  110. btnSync.Accepting += (s, e) => _sync.Invoke ();
  111. var btnMethod = new Button { X = 80, Y = 18, Text = "Load Data Method" };
  112. btnMethod.Accepting += async (s, e) => await MethodAsync ();
  113. var btnClearData = new Button { X = 80, Y = 20, Text = "Clear Data" };
  114. btnClearData.Accepting += (s, e) =>
  115. {
  116. _itemsList.Source = null;
  117. LogJob ("Cleaning Data");
  118. };
  119. var btnQuit = new Button { X = 80, Y = 22, Text = "Quit" };
  120. btnQuit.Accepting += (s, e) => Application.RequestStop ();
  121. win.Add (
  122. _itemsList,
  123. _btnActionCancel,
  124. _logJob,
  125. text,
  126. _btnLogarithmic,
  127. _numberLog,
  128. _btnSmooth,
  129. _numberSmooth,
  130. btnAction,
  131. btnLambda,
  132. btnHandler,
  133. btnSync,
  134. btnMethod,
  135. btnClearData,
  136. btnQuit
  137. );
  138. void Win_Loaded (object sender, EventArgs args)
  139. {
  140. _btnActionCancel.SetFocus ();
  141. win.IsModalChanged -= Win_Loaded;
  142. }
  143. win.IsModalChanged += Win_Loaded;
  144. Application.Run (win);
  145. win.Dispose ();
  146. Application.Shutdown ();
  147. }
  148. private bool LogTimeout ()
  149. {
  150. _numberLog.Value++;
  151. _logarithmicTimeout.AdvanceStage ();
  152. return true;
  153. }
  154. private bool SmoothTimeout ()
  155. {
  156. _numberSmooth.Value++;
  157. _smoothTimeout.AdvanceStage ();
  158. return true;
  159. }
  160. private void StartStopLogTimeout (object sender, CommandEventArgs e)
  161. {
  162. if (_timeoutObj != null)
  163. {
  164. _btnLogarithmic.Text = "Start Log Counter";
  165. Application.TimedEvents.Remove (_timeoutObj);
  166. _timeoutObj = null;
  167. }
  168. else
  169. {
  170. _btnLogarithmic.Text = "Stop Log Counter";
  171. _logarithmicTimeout = new LogarithmicTimeout (TimeSpan.FromMilliseconds (500), LogTimeout);
  172. _timeoutObj = Application.TimedEvents.Add (_logarithmicTimeout);
  173. }
  174. }
  175. private void StartStopSmoothTimeout (object sender, CommandEventArgs e)
  176. {
  177. if (_timeoutObjSmooth != null)
  178. {
  179. _btnSmooth.Text = "Start Smooth Counter";
  180. Application.TimedEvents.Remove (_timeoutObjSmooth);
  181. _timeoutObjSmooth = null;
  182. }
  183. else
  184. {
  185. _btnSmooth.Text = "Stop Smooth Counter";
  186. _smoothTimeout = new SmoothAcceleratingTimeout (TimeSpan.FromMilliseconds (500), TimeSpan.FromMilliseconds (50), 0.5, SmoothTimeout);
  187. _timeoutObjSmooth = Application.TimedEvents.Add (_smoothTimeout);
  188. }
  189. }
  190. private async void CallLoadItemsAsync ()
  191. {
  192. _cancellationTokenSource = new CancellationTokenSource ();
  193. _itemsList.Source = null;
  194. LogJob ("Clicked the button");
  195. if (_btnActionCancel.Text != "Cancel")
  196. {
  197. _btnActionCancel.Text = "Cancel";
  198. }
  199. else
  200. {
  201. _btnActionCancel.Text = "Cancelable Load Items";
  202. await _cancellationTokenSource.CancelAsync ();
  203. }
  204. try
  205. {
  206. if (_cancellationTokenSource.Token.IsCancellationRequested)
  207. {
  208. _cancellationTokenSource.Token.ThrowIfCancellationRequested ();
  209. }
  210. LogJob ($"Calling task Thread:{Thread.CurrentThread.ManagedThreadId} {DateTime.Now}");
  211. ObservableCollection<string> items = await Task.Run (LoadItemsAsync, _cancellationTokenSource.Token);
  212. if (!_cancellationTokenSource.IsCancellationRequested)
  213. {
  214. LogJob (
  215. $"Returned from task Thread:{Thread.CurrentThread.ManagedThreadId} {DateTime.Now}"
  216. );
  217. await _itemsList.SetSourceAsync (items);
  218. LogJob (
  219. $"Finished populate list view Thread:{Thread.CurrentThread.ManagedThreadId} {DateTime.Now}"
  220. );
  221. _btnActionCancel.Text = "Cancelable Load Items";
  222. }
  223. else
  224. {
  225. LogJob ("Task was canceled!");
  226. }
  227. }
  228. catch (OperationCanceledException ex)
  229. {
  230. LogJob (ex.Message);
  231. }
  232. }
  233. private async void LoadData ()
  234. {
  235. _itemsList.Source = null;
  236. LogJob ("Loading task");
  237. ObservableCollection<string> items = await LoadDataAsync ();
  238. LogJob ("Returning from task");
  239. await _itemsList.SetSourceAsync (items);
  240. }
  241. private async Task<ObservableCollection<string>> LoadDataAsync ()
  242. {
  243. _itemsList.Source = null;
  244. LogJob ("Starting delay");
  245. await Task.Delay (3000);
  246. LogJob ("Finished delay");
  247. return
  248. [
  249. "One",
  250. "Two",
  251. "Three",
  252. "Four",
  253. "Five",
  254. "Six",
  255. "Seven",
  256. "Eight",
  257. "Nine",
  258. "Ten",
  259. "Four",
  260. "Five",
  261. "Six",
  262. "Seven",
  263. "Eight",
  264. "Nine",
  265. "Ten"
  266. ];
  267. }
  268. private async Task<ObservableCollection<string>> LoadItemsAsync ()
  269. {
  270. // Do something that takes lot of times.
  271. LogJob ($"Starting delay Thread:{Thread.CurrentThread.ManagedThreadId} {DateTime.Now}");
  272. await Task.Delay (5000);
  273. LogJob ($"Finished delay Thread:{Thread.CurrentThread.ManagedThreadId} {DateTime.Now}");
  274. return ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"];
  275. }
  276. private void LogJob (string job)
  277. {
  278. _log.Add (job);
  279. _logJob.MoveDown ();
  280. }
  281. private async Task MethodAsync ()
  282. {
  283. _itemsList.Source = null;
  284. LogJob ("Loading task method");
  285. ObservableCollection<string> items = ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"];
  286. await Task.Delay (3000);
  287. LogJob ("Returning from task method");
  288. await _itemsList.SetSourceAsync (items);
  289. _itemsList.SetNeedsDraw ();
  290. }
  291. }