using System; using System.Collections.Generic; using System.Threading; interface Task{ void doTask(); } class TaskA : Task{ public void doTask(){ Console.WriteLine("ABC"); } } class TaskB : Task{ public void doTask(){ for(;;){ Console.Write("."); Thread.Sleep(0); //Cancel用 } } } class Tasker{ private Thread th; private EventWaitHandle wh = new ManualResetEvent(false); private Queue queue = new Queue(); private bool end = false; public void Start(){ if(th!=null){throw new Exception();} th = new Thread(ThreadMain); th.Start(); } public void AddTask(Task t){ lock(queue){ queue.Enqueue(t); wh.Set(); } } public void Cancel(){ th.Interrupt(); } public void Join(){ lock(queue){ end = true; wh.Set(); } th.Join(); } private void ThreadMain(){ try{ Console.WriteLine("Start"); for(;;){ Task t; lock(queue){ t = queue.Count==0 ? null : queue.Dequeue(); if(t==null){ if(end){ Console.WriteLine("End"); return; } wh.Reset(); } } if(t==null){ Console.WriteLine("Wait"); wh.WaitOne(Timeout.Infinite); } else{ t.doTask(); Thread.Sleep(0); //Cancel用 } } } catch(ThreadInterruptedException){ Console.WriteLine(); Console.WriteLine("Cancel"); } } } class Test{ public static void Main(){ { Tasker te = new Tasker(); te.Start(); Thread.Sleep(50); //Taskが無いのでスレッドはWaitになる te.AddTask(new TaskA()); Thread.Sleep(50); //TaskAはすぐ終わるのでスレッドはWaitになる te.AddTask(new TaskB()); Thread.Sleep(1); te.Cancel(); //TaskBは終わらないので中断 te.Join(); //Threadの終了を待つ } Console.WriteLine("--------------"); { Tasker te = new Tasker(); te.AddTask(new TaskA()); te.Start(); Thread.Sleep(50); //TaskAはすぐ終わるのでスレッドはWaitになる te.Join(); //Waitから復帰させThreadの終了を待つ } } }