This is untested, but it is an elegant way to do this with .net based primitives:
class Processor<T> { Action<T> action; Queue<T> queue = new Queue<T>(); public Processor(Action<T> action) { this.action = action; new Thread(new ThreadStart(ThreadProc)).Start(); } public void Queue(T data) { lock (queue) { queue.Enqueue(data); Monitor.Pulse(queue); } } void ThreadProc() { Monitor.Enter(queue); Queue<T> copy; while (true) { if (queue.Count == 0) { Monitor.Wait(queue); } copy = new Queue<T>(queue); queue.Clear(); Monitor.Exit(queue); foreach (var item in copy) { action(item); } Monitor.Enter(queue); } } }
Program Example:
class Program { static void Main(string[] args) { Processor<int> p = new Processor<int>((data) => { Console.WriteLine(data); }); p.Queue(1); p.Queue(2); Console.Read(); p.Queue(3); } }
This is a non-queued version, a queue version may be preferred:
object sync = new object(); AutoResetEvent e = new AutoResetEvent(false); bool pending = false; public SetData(MyData d) { lock(sync) { if (pending) throw(new CanNotSetDataException()); this.d=d; pending = true; } e.Set(); // notify that new data is available } void Runner() // this runs in separate thread and waits for d to be set to a new value { while (true) { e.WaitOne(); // waits for new data to process DoLongOperationWith_d(d); lock(sync) { pending = false; } } }
source share