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<Task> queue = new Queue<Task>();
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の終了を待つ
}
}
}