I am writing a multi threaded application and I have concerns with 2 threads access a queue
Thread 1 puts items in a queue for processing Thread 2 removes items from the queue to process
Thread 1 runs once a minute due to the nature of the data it is pulling. Thread 2 is always running, it removes an item from the queue and sleeps for 100ms. I have to do this to ensure that I don't overwhelm a service it calls when it dequeues an item.
I assume both threads should place a lock on the queue when adding or removing items from it. Are there any further considerations? For instance say Thread 1 has a lock and Thread 2 tries to access it. Does Thread 2 simply know to wait and resume once the lock is removed?
Would it be preferable to use a ConcurrentQueue and just TryDequeue and if it fails just go about its 100 ms sleep?
Thanks in advance
It's even easier if you use a BlockingCollection<T> like I do in NuGet's VS console dispatcher for my PostKey/WaitKey implementation. The consuming thread calls Take(...) which will block until another thread calls Add(...). There is no need to poll. Additionally, you may wish to pass a cancellation token to the Take method so another thread can stop the consumer thread if it's currently waiting for an Add that will never come. Here are the relevant methods:
private readonly BlockingCollection<VsKeyInfo> _keyBuffer =
new BlockingCollection<VsKeyInfo>();
private CancellationTokenSource _cancelWaitKeySource;
// place a key into buffer
public void PostKey(VsKeyInfo key)
{
if (key == null)
{
throw new ArgumentNullException("key");
}
_keyBuffer.Add(key);
}
// signal thread waiting on a key to exit Take
public void CancelWaitKey()
{
if (_isExecutingReadKey && !_cancelWaitKeySource.IsCancellationRequested)
{
_cancelWaitKeySource.Cancel();
}
}
// wait for a key to be placed on buffer
public VsKeyInfo WaitKey()
{
try
{
// raise the StartWaitingKey event on main thread
RaiseEventSafe(StartWaitingKey);
// set/reset the cancellation token
_cancelWaitKeySource = new CancellationTokenSource();
_isExecutingReadKey = true;
// blocking call
VsKeyInfo key = _keyBuffer.Take(_cancelWaitKeySource.Token);
return key;
}
catch (OperationCanceledException)
{
return null;
}
finally
{
_isExecutingReadKey = false;
}
}
See http://nuget.codeplex.com/SourceControl/changeset/view/45e353aca7f4#src%2fVsConsole%2fConsole%2fConsole%2fConsoleDispatcher.cs for more details.
As long as you are locking on the same "sync" object, thread 2 will wait for thread 1 and vice-versa. I think the ConcurrentQueue is a good idea because it's already specified as thread safe.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With