Reputation: 4609
I am wondering how to do inside executional thread to be thread safe, let me explain it by example:
lets say that I want to have pipeline of commands which should be executed continuously one by one, but in my thread I can't wait for them. Thread is normally slept, is awaeken if some command is enqueued, then it executes all commands in the queue and again goes to sleeping mode until new command is being enqueued. something like:
public void Enqueue(ICommand command)
{
this.queue.Enqueue(command);
this.synchroHandler.Set();
}
private void Pipeline()
{
while (true)
{
this.synchroHandler.WaitOne();
while (this.queue.Count > 0)
{
ICommand command = this.queue.Dequeue();
command.Execute();
}
// what if command will be enqueued between previous command - HERE
// ... and this command HERE
this.synchroHandler.Reset();
}
}
public void Main()
{
this.queue = new ThreadSafeQueue<ICommand>();
this.computionHandler = new ManualResetEvent(false);
Thread thread = new Thread(new ThreadStart(this.Pipeline));
thread.Start();
// start adding commands to pipeline
this.Enqueue(command1);
this.Enqueue(command2);
...
}
lets say my implementation of queue is thread-safe so this.queue.Count, this.queue.Enqueue and this.queue.Dequeue use same lock. Ss shown in the example if public Enqueue() will be invoked between the "}" and this.synchroHandler.Reset(); thread will ends up slept even if it has one item in the queue (this.synchroHandler.Set() will be invoked right before this.synchroHandler.Reset()). Any idea how to make this schema thread-safe?
Upvotes: 2
Views: 909
Reputation: 1035
Can you change it to spin? So, every 10ms, the thread wakes up and checks to see if the Queue has an item, otherwise is goes to sleep again.
while (true)
{
while (this.queue.Count > 0)
{
ICommand command = this.queue.Dequeue();
command.Execute();
}
Thread.Sleep(10);
}
Upvotes: 0
Reputation: 1013
You should call this.synchroHandler.Reset() right after WaitOne().
Therefore if Queue is called before the Reset, you will enter the while loop and if its called after you checked the queue.Count, the next time you call WaitOne(), it will return immediately and go into the while loop.
Upvotes: 0
Reputation: 54148
Check out BlockingCollection<T>
, thread safe producer-consumer in System.Collections.Concurrent namespace.
Upvotes: 2