Skip to content

Instantly share code, notes, and snippets.

@takeshik
Created June 13, 2010 07:34
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save takeshik/436441 to your computer and use it in GitHub Desktop.
Save takeshik/436441 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace ConsoleApplication1
{
public class TaskQueue : IDisposable
{
//仕事キュー
private readonly Queue<ThreadStart> _taskQueue = new Queue<ThreadStart>();
//仕事をするスレッド
private readonly List<Thread> _threads;
//仕事ができたら通知してくれるイベント
private readonly ManualResetEvent _notifyEvent = new ManualResetEvent(false);
//この変数はロックだ。そしてコレを見てくれる君達もロックだ。
private readonly object _lockObject = new object();
//スレッド群の生成
public TaskQueue(int threadCount)
{
this._threads = Enumerable.Range(0, 3).Select(_ => new Thread(this.ThreadRunning)).ToList();
this._threads.ForEach(t => t.Start());
}
//一応、リソース解放時に停止命令を出すようにするよ。
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
this.Stop();
this._notifyEvent.Dispose();
}
~TaskQueue()
{
this.Dispose(false);
}
//スレッド群の停止
public void Stop()
{
if (this._threads == null)
{
return;
}
//終了のお知らせ
this._threads.ForEach(t => t.Interrupt());
//確実にとめる
this._threads.ForEach(t => t.Join());
}
//タスクを追加する
public void AddTask(ThreadStart inTask)
{
//タスクを追加
lock (this._lockObject)
{
this._taskQueue.Enqueue(inTask);
}
//飯ができたぞー
this._notifyEvent.Set();
}
//キューに残っている仕事の確認
public int Count
{
get
{
lock (this._lockObject)
{
return this._taskQueue.Count;
}
}
}
//スレッドの中で動作
private void ThreadRunning()
{
try
{
ThreadStart task;
while (true)
{
//仕事が来るまで寝る。 ニートになる。リーマン乙。
this._notifyEvent.WaitOne();
//仕事を他にとられないようにリセット。
this._notifyEvent.Reset();
while (true)
{
//何か仕事はないかな?
lock (this._lockObject)
{
if (!this._taskQueue.Any())
{
//仕事がないので寝る
break;
}
//内定
task = this._taskQueue.Dequeue();
}
//仕事をする リーマン状態
task();
//次の仕事を探しに行く。
}
}
}
catch (ThreadInterruptedException)
{
//おしまい
}
}
};
//ここから動作確認用のサンプルソース
class Program
{
static void Main(string[] args)
{
//タスクキューの作成 最大3つまで同時動作
using (TaskQueue task = new TaskQueue(3))
{
while (true)
{
Console.WriteLine("タスクキューサンプル");
Console.WriteLine(" タスクキュー3つまでなら同時に仕事をさばきます。");
Console.WriteLine(" スペースキーを押して仕事を積みます。");
Console.WriteLine("q 終了");
Console.WriteLine("スペース 仕事を積む");
Console.WriteLine("その他 画面の更新");
ConsoleKeyInfo key = Console.ReadKey(false);
Console.Clear();
if (key.KeyChar == 'Q' || key.KeyChar == 'q')
{
Console.WriteLine("( ゚д゚)ぽかーん");
break;
}
if (key.KeyChar == ' ')
{
int time = (Environment.TickCount % 5000) + 1000;
string name = (time % 3 == 0) ? "開発業務" : (time % 3 == 1) ? "資料作成" : "サポート業務";
Console.WriteLine("( ゚д゚)< この仕事やっといて、今日中に。");
//タスクの追加
task.AddTask(() =>
{
//なにか仕事をする
Thread.Sleep(time);
//終わったのでつぶやく。
Console.WriteLine("( ´∀`)< おわた。{0}ミリ秒かかる仕事({1})が終わりました。", time, name);
});
Console.WriteLine("( ´∀`)< {0}ミリ秒かかる仕事({1})が積まれました", time, name);
}
//現在の仕事の数を表示.
int workCount = task.Count;
Console.WriteLine("");
Console.WriteLine("現在 {0} の仕事に手がつけられていません。", workCount);
if (workCount > 5)
{
Console.WriteLine("( ´∀`)< ブラック乙");
}
else if (workCount > 3)
{
Console.WriteLine("( ´∀`)< 帰れない。。。");
}
else if (workCount > 2)
{
Console.WriteLine("( ´∀`)< これは、終電だな");
}
else if (workCount > 0)
{
Console.WriteLine("( ´∀`)< タスクオーバー。残業だな");
}
else if (workCount <= 0)
{
Console.WriteLine("( ´∀`)< キャパ内の仕事量です。");
}
Console.WriteLine("");
Console.WriteLine("");
Console.WriteLine("");
Console.WriteLine("");
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment