C# で メッセージキュー
- 動機
C#でスレッド処理を行うときメッセージキューが使いたくなった
「受け取ったパラメータに対する処理」が別スレッドで動いて
渡すパラメータがキューイングされてれば良いって状況で
プロセス間メッセージとかそういうのは無くていいから
簡単に実現できねーかな〜と
別用途に書いたワーカースレッドクラスを転用したら
それらしい事ができたのでメモ
- WorkerThread
別用途で書いたワーカースレッドクラス
単一のスレッド内でキューイングされたActionを処理する
殆どの場合はThreadPoolを直接使えば良いんだけど
発行した処理が同時実行された場合の同期が面倒だったので
こういうのを作った
public class WorkerThread : IDisposable { private Queue<Action> jobs = new Queue<Action>(); private volatile bool running = true; private ManualResetEvent ev = new ManualResetEvent(false); public WorkerThread() { ThreadPool.QueueUserWorkItem(new WaitCallback(Execute)); } private void Execute(object o) { while (ev.WaitOne()) { if (!running) { break; } Action actor = null; lock (jobs) { if (jobs.Count > 0) { actor = jobs.Dequeue(); } else { ev.Reset(); } } if (actor != null) { actor(); } } } public void Add(Action job) { lock (jobs) { jobs.Enqueue(job); ev.Set(); } } #region IDisposable メンバ public void Dispose() { running = false; ev.Set(); } #endregion }
これ自体の使い方は new して Action をAddしていくだけ
Disposeもあるけど呼ばなくたっていい
WorkerThread thread = new WorkerThread(); thread.Add(ほげほげ);
- 使い方
以下のクラスはメッセージキューを使ったワーカークラスのようなもので
Add でパラメータをキューに入れ
Run でキューからパラメータを取り出し処理する
といったイメージ
先程のクラスを転用すると以下のようにかける
class Worker { MYCS.WorkerThread thread = new MYCS.WorkerThread(); public void Add(string message) { thread.Add(delegate() { Run(message); }); } private void Run(string message) { Console.WriteLine(message); } }
簡単だね