Created
June 13, 2010 07:34
-
-
Save takeshik/436441 to your computer and use it in GitHub Desktop.
by @super_rti / from http://d.hatena.ne.jp/rti7743/20100612/1276375504
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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