fork(1) download
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading;
  4.  
  5. interface Task{
  6. void doTask();
  7. }
  8. class TaskA : Task{
  9. public void doTask(){
  10. Console.WriteLine("ABC");
  11. }
  12. }
  13. class TaskB : Task{
  14. public void doTask(){
  15. for(;;){
  16. Console.Write(".");
  17. Thread.Sleep(0); //Cancel用
  18. }
  19. }
  20. }
  21.  
  22. class Tasker{
  23. private Thread th;
  24. private EventWaitHandle wh = new ManualResetEvent(false);
  25. private Queue<Task> queue = new Queue<Task>();
  26. private bool end = false;
  27.  
  28. public void Start(){
  29. if(th!=null){throw new Exception();}
  30. th = new Thread(ThreadMain);
  31. th.Start();
  32. }
  33. public void AddTask(Task t){
  34. lock(queue){
  35. queue.Enqueue(t);
  36. wh.Set();
  37. }
  38. }
  39. public void Cancel(){
  40. th.Interrupt();
  41. }
  42. public void Join(){
  43. lock(queue){
  44. end = true;
  45. wh.Set();
  46. }
  47. th.Join();
  48. }
  49.  
  50. private void ThreadMain(){
  51. try{
  52. Console.WriteLine("Start");
  53. for(;;){
  54. Task t;
  55. lock(queue){
  56. t = queue.Count==0 ? null : queue.Dequeue();
  57. if(t==null){
  58. if(end){
  59. Console.WriteLine("End");
  60. return;
  61. }
  62. wh.Reset();
  63. }
  64. }
  65. if(t==null){
  66. Console.WriteLine("Wait");
  67. wh.WaitOne(Timeout.Infinite);
  68. }
  69. else{
  70. t.doTask();
  71. Thread.Sleep(0); //Cancel用
  72. }
  73. }
  74. }
  75. catch(ThreadInterruptedException){
  76. Console.WriteLine();
  77. Console.WriteLine("Cancel");
  78. }
  79. }
  80. }
  81.  
  82. class Test{
  83. public static void Main(){
  84. {
  85. Tasker te = new Tasker();
  86. te.Start();
  87. Thread.Sleep(50); //Taskが無いのでスレッドはWaitになる
  88. te.AddTask(new TaskA());
  89. Thread.Sleep(50); //TaskAはすぐ終わるのでスレッドはWaitになる
  90. te.AddTask(new TaskB());
  91. Thread.Sleep(1);
  92. te.Cancel(); //TaskBは終わらないので中断
  93. te.Join(); //Threadの終了を待つ
  94. }
  95. Console.WriteLine("--------------");
  96. {
  97. Tasker te = new Tasker();
  98. te.AddTask(new TaskA());
  99. te.Start();
  100. Thread.Sleep(50); //TaskAはすぐ終わるのでスレッドはWaitになる
  101. te.Join(); //Waitから復帰させThreadの終了を待つ
  102. }
  103. }
  104. }
  105.  
Success #stdin #stdout 0.03s 38056KB
stdin
Standard input is empty
stdout
Start
Wait
ABC
Wait
...................................................................
Cancel
--------------
Start
ABC
Wait
End