Assume we have two threads working with a method that execute below:
while(true){
if(Queue.Count() <= 0){
wait();
}
object anObject = Queue.Dequeue();
}
Now the problem occurs when Queue has one element init, Thread 1 is about to execute Queue.Count line, Thread 2 about is on Queue.Dequeue() and execution priority is on Thread 1.
As this situation occurs, Thread 1 will throw an exception because, Queue.Count() will return 1 and it will try to dequeue an object from an empty queue. How can I handle this? What is the best solution if I want to dequeue safely? Should I use syncronized or lock something?
Best regards,
Kemal
The best solution, assuming you are using .NET 4.0 or higher and really need a queue, is to switch to using ConcurrentQueue and it's TryDequeue method. ConcurrentQueue is thread safe.
That said, it looks from your code snippet like what you are really looking for is a thread safe producer/consumer queue. In that case, use the BlockingCollection class and it's Take method:
while(true){
// This will block until an item becomes available to take.
// It is also thread safe, and can be called by multiple
// threads simultaneously. When an item is added, only one
// waiting thread will Take() it
object anObject = myBlockingCollection.Take();
// do something with anObject
}
You can use thread safe queue ConcurrentQueue.
or if you don't want to use it
while (true)
{
Monitor.Enter(lockObj);
try
{
if (Queue.Count <= 0)
{
Monitor.Wait(lockObj);
}
object anObject = Queue.Dequeue();
}
finally
{
Monitor.Exit(lockObj);
}
}
or if using lock
while (true)
{
lock(lockObj)
{
if (Queue.Count <= 0)
{
Monitor.Wait(lockObj);
}
object anObject = Queue.Dequeue();
}
}
Try this pattern:
Producer
public void Produce(object o)
{
lock (_queueLock)
{
_queue.Enqueue(o);
Monitor.Pulse(_queueLock);
}
}
Consumer
public object Consume()
{
lock (_queueLock)
{
while (_queue.Count==0)
{
Monitor.Wait(_queueLock);
}
return _queue.Dequeue();
}
}
Lock the queue before accessing it.
lock (Queue) {
// blah blah
}
EDIT
while(true){
lock (Queue) {
if (Queue.Count() > 0) {
// Dequeue only if there is still something in the queue
object anObject = Queue.Dequeue();
}
}
}
Related
I want to have a FIFO Queue with the following requirements:
If queue is empty, wait for one element to be added
Start processing as soon as one element is in the Q
If elements pending in the Q are more than X, drop them.
I used a BlockingCollection like this:
public LoggerReal()
{
main = (frmMain)Application.OpenForms[0];
LogQueue = new BlockingCollection<logEntry>(GlobalSettings.LogQueueSize);
Task.Run(() => {
foreach (logEntry LE in LogQueue.GetConsumingEnumerable()) {
try {
ProcessLogEntry(LE);
} catch (Exception E) {
functions.Logger.log("Error processing logEntry" + E.Message, "LOGPROCESSING", LOGLEVEL.ERROR);
functions.printException(E);
}
}
functions.Logger.log("Exiting Queue Task", "LOGPROCESSING", LOGLEVEL.ERROR);
});
}
However, I noticed that the logs seems to show only when the queue was full.
ProcessLogEntry function simply puts them into a ListBox.
I tried using simple queue with no luck.
As far as I could tell, ConcurrentQueue and other Queue might not fulfill these requirements, or am I wrong? I start the Queue processor into a Task so it can be waiting forever, that is not an issue, but it needs to start processing as soon as data is available.
If I understand correctly your requirements, you can use a regular Queue<T> with simple Monitor based signaling like this:
Members:
private readonly int maxSize;
private readonly Queue<logEntry> logQueue;
private bool stopRequest;
Constructor:
maxSize = GlobalSettings.LogQueueSize;
logQueue = new Queue<logEntry>(maxSize);
Producer method:
public void Add(logEntry logEntry)
{
lock (logQueue)
{
if (stopRequest) return;
logQueue.Enqueue(logEntry);
if (logQueue.Count == 1)
Monitor.Pulse(logQueue);
}
}
Method to stop the process worker:
public void Stop()
{
lock (logQueue)
{
if (stopRequest) return;
stopRequest = true;
Monitor.Pulse(logQueue);
}
}
Process worker (the method called with Task.Run):
private void ProcessWorker()
{
while (true)
{
logEntry LE;
lock (logQueue)
{
while (!stopRequest && logQueue.Count == 0)
Monitor.Wait(logQueue);
if (stopRequest) break;
if (logQueue.Count > maxSize)
{
logQueue.Clear();
continue;
}
LE = logQueue.Dequeue();
}
try
{
ProcessLogEntry(LE);
}
catch (Exception E)
{
functions.Logger.log("Error processing logEntry" + E.Message, "LOGPROCESSING", LOGLEVEL.ERROR);
functions.printException(E);
}
}
functions.Logger.log("Exiting Queue Task", "LOGPROCESSING", LOGLEVEL.ERROR);
}
This is just to get the idea, you can further tune the implementation to better suit your needs.
Your title is somewhat confusing (FIFO is a queue, and a blocking collection waits/blocks by definition?). However, I'm going to guess at what you want here...
I'm going to assume you want 2 threads, one which is adding to the queue (writer), and the other which is blocked/waiting to process items as soon as they're added (reader).
Create a blocking collection:
var dataSink = new BlockingCollection<logEntry]>(new ConcurrentQueue<logEntry>());
The 'writer' thread simply adds and continues on it's way
dataSink.Add(logEntryToAdd); // Add to collection and continue
The 'reader' thread blocks until an item is added to the queue
while (dataSink.Count > 0)
{
ProcessLogEntry(dataSink.Take());
}
I'm not sure about your overflow "X" but perhaps during the 'add' operation you can get the count and if it exceeds 'x' either don't add or dequeue the first item (depends on what your logic flow entails).
Obviously, be sure that the UI thread is NOT blocked (UI thread should not be the 'reader', create a 3rd thread if needed which blocks/reads from the queue and then notifies the UI via an invoke to update the Listbox) otherwise your UI will become unresponsive...
So in the end, I used BlockingCollection, but I do a while loop with tryTake instead of using the ConsumingEnumerable:
Task.Run(() => {
while (!LogQueue.IsCompleted) {
logEntry LE;
LogQueue.TryTake(out LE, Timeout.Infinite);
try {
ProcessLogEntry(LE);
} finally {
// Do nothing, because if logging cause issue, logging exception is likely to do so as well...
}
}
//functions.Logger.log("Exiting Queue Task", "LOGPROCESSING", LOGLEVEL.ERROR); // Will not work if exiting Q
});
I have a class that provides thread-safe access to LinkedList<> (adding and reading items).
class LinkedListManager {
public static object locker = new object();
public static LinkedList<AddXmlNodeArgs> tasks { get; set; }
public static EventWaitHandle wh { get; set; }
public void AddItemThreadSafe(AddXmlNodeArgs task) {
lock (locker)
tasks.AddLast(task);
wh.Set();
}
public LinkedListNode<AddXmlNodeArgs> GetNextItemThreadSafe(LinkedListNode<AddXmlNodeArgs> prevItem) {
LinkedListNode<AddXmlNodeArgs> nextItem;
if (prevItem == null) {
lock (locker)
return tasks.First;
}
lock (locker) // *1
nextItem = prevItem.Next;
if (nextItem == null) { // *2
wh.WaitOne();
return prevItem.Next;
}
lock (locker)
return nextItem;
}
}
}
I have 3 threads: 1st - writes data to tasks; 2nd and 3rd - read data from tasks.
In 2nd and 3rd threads I retrieve data from tasks by calling GetNextItemThreadSafe().
The problem is that sometimes GetNextItemThreadSafe() returns null, when parameter of method (prevItem) is not null`.
Question:
Can a thread somehow jump over lock(locker) (// *1) and get to // *2 at once ??
I think it's the only way to get a return value = null from GetNextItemThreadSafe()...
I've spend a whole day to find the mistake, but it's extremely hard because it seems to be almost impossible to debug it step by step (tasks contains 5.000 elements and error occurs whenever it wants). Btw sometimes program works fine - without exception.
I'm new to threads so maybe I'm asking silly questions...
Not clear what you're trying to achieve. Are both threads supposed to get the same elements of the linked list ? Or are you trying to have 2 threads process the tasks out of the list in parallel ? If it's the second case, then what you are doing cannot work. You'd better look at BlockingCollection which is thread-safe and designed for this kind of multi-threaded producers/consumers patterns.
A lock is only active when executing the block of code declared following the lock. Since you lock multiple times on single commands, this effectively degenerates to only locking the single command that follows the lock, after which another thread is free to jump in and consume the data. Perhaps what you meant is this:
public LinkedListNode<AddXmlNodeArgs> GetNextItemThreadSafe(LinkedListNode<AddXmlNodeArgs> prevItem) {
LinkedListNode<AddXmlNodeArgs> nextItem;
LinkedListNode<AddXmlNodeArgs> returnItem;
lock(locker) { // Lock the entire method contents to make it atomic
if (prevItem == null) {
returnItem = tasks.First;
}
// *1
nextItem = prevItem.Next;
if (nextItem == null) { // *2
// wh.WaitOne(); // Waiting in a locked block is not a good idea
returnItem = prevItem.Next;
}
returnItem = nextItem;
}
return returnItem;
}
}
Note that only assignments (as opposed to returns) occur within the locked block and there is a single return point at the bottom of the method.
I think the solution is the following:
In your Add method, add the node and set the EventWaitHandle both inside the same lock
In the Get method, inside a lock, check if the next element is empty and inside the same lock, Reset the EventWaitHandle. Outside of the lock, wait on the EventWaitHandle.
Let's say I have a list and am streaming data from a namedpipe to that list.
hypothetical sample:
private void myStreamingThread()
{
while(mypipe.isconnected)
{
if (mypipe.hasdata)
myList.add(mypipe.data);
}
}
Then on another thread I need to read that list every 1000ms for example:
private void myListReadingThread()
{
while(isStarted)
{
if (myList.count > 0)
{
//do whatever I need to.
}
Thread.Sleep(1000);
}
}
My priority here is to be able to read the list every 1000 ms and do whatever I need with the list but at the same time it is very important to be able to get the new data from it that comes from the pipe.
What is a good method to come with this ?
Forgot to mention I am tied to .NET 3.5
I would recommend using a Queue with a lock.
Queue<string> myQueue = new Queue<string>();
private void myStreamingThread()
{
while(mypipe.isconnected)
{
if (mypipe.hasdata)
{
lock (myQueue)
{
myQueue.add(mypipe.data);
}
}
}
}
If you want to empty the queue every 1000 ms, do not use Thread.Sleep. Use a timer instead.
System.Threading.Timer t = new Timer(myListReadingProc, null, 1000, 1000);
private void myListReadingProc(object s)
{
while (myQueue.Count > 0)
{
lock (myQueue)
{
string item = myQueue.Dequeue();
// do whatever
}
}
}
Note that the above assumes that the queue is only being read by one thread. If multiple threads are reading, then there's a race condition. But the above will work with a single reader and one or more writers.
I would suggest using a ConcurrentQueue (http://msdn.microsoft.com/en-us/library/dd267265.aspx). If you use a simple List<> then you will encourter a lot threading issues.
The other practice would be to use a mutex called outstandingWork and wait on it instead of Thread.Sleep(). Then when you enqueue some work you pulse outstandingWork. This means that you sleep when no work is available but start processing work immediately instead of sleep the entire 1 second.
Edit
As #Prix pointed out, you are using .Net 3.5. So you cannot use ConcurrentQueue. Use the Queue class with the following
Queue<Work> queue;
AutoResetEvent outstandingWork = new AutoResetEvent(false);
void Enqueue(Work work)
{
lock (queue)
{
queue.Enqueue(work);
outstandingWork.Set();
}
}
Work DequeMaybe()
{
lock (queue)
{
if (queue.Count == 0) return null;
return queue.Dequeue();
}
}
void DoWork()
{
while (true)
{
Work work = DequeMaybe();
if (work == null)
{
outstandingWork.WaitOne();
continue;
}
// Do the work.
}
}
I have implemented a generic ObjectPool class but have experienced that it sometime deadlocks (happens at Monitor.Wait(poolLock))
Can anyone spot the error?
public class ObjectPool<T> where T : new()
{
private readonly object poolLock = new object();
Stack<T> stack = null;
public ObjectPool(int count)
{
stack = new Stack<T>(count);
for (int i=0; i<count; i++)
stack.Push(new T());
}
public T Get()
{
lock (poolLock)
{
//if no more left wait for one to get Pushed
while (stack.Count < 1)
Monitor.Wait(poolLock);
return stack.Pop();
}
}
public void Put(T item)
{
lock (poolLock)
{
stack.Push(item);
//If adding first send signal
if (stack.Count == 1)
Monitor.Pulse(poolLock);
}
}
usage
try
{
service = myPool.Get();
}
finally
{
if (service != null)
myPool.Put(service);
}
The deadlock is probably happening with a stack.Count > 0 . That means you have a Wait/Pulse problem. It is not a bad idea to always call Pulse after a Push(). Or at least when Count < 5 or so. Remember that the Wait/Pulse mechanism does not have a memory.
A scenario:
Thread A tries to Get from an empty
Pool, and does a Wait()
Thread B tries
to Get from an empty Pool, and does a
Wait()
Thread C Puts into the Pool, Does a Pulse()
Thread D Puts back into the Pool and does not Pulse (Count == 2)
Thread A is activated and Gets its Item.
Thread B is left Waiting. With little hope fro recovery.
i see it a little more clear now. I must have a reader lock, right?
public T Get()
{
lock (readerLock)
{
lock (poolLock)
{
//if no more left wait for one to get Pushed
while (stack.Count < 1)
Monitor.Wait(poolLock);
return stack.Pop();
}
}
}
Just a guess but what about removing the "stack.Count == 1" condition and always issuing a Pulse inside of the Put function? Maybe two Puts are being called quickly in sequence and only one waiting thread is being awaken..
Henk answered your question. Following condition is not correct:
if (stack.Count == 1)
I have the scenario where a command comes in over a socket which requires a fair amount of work. Only one thread can process the data at a time. The commands will come in faster than can process it. Over time there will be quiet a back log.
The good part is that I can discard waiting threads and really only have to process the last one that is waiting - (or process the first one in and discard all the other once). I was thinking about using a semaphore to control the critical section of code and to use a boolean to see if there are any threads blocking. If there are blocking thread I would just discard the thread.
My mind is drawing a blank on how to implement it nicely I would like to implement it with out using an integer or boolean to see if there is a thread waiting already.
I am coding this in c#
You can use Monitor.TryEnter to see whether a lock is already taken on an object:
void ProcessConnection(TcpClient client)
{
bool lockTaken = false;
Monitor.TryEnter(lockObject, out lockTaken);
if (!lockTaken)
{
client.Close();
return;
}
try
{
// long-running process here
}
finally
{
Monitor.Exit(lockObject);
client.Close();
}
}
Note that for this to work you'll still have to invoke the method in a thread, for example:
client = listener.AcceptTcpClient();
ThreadPool.QueueUserWorkItem(notused => ProcessConnection(client));
FYI, the lock statement is just sugar for:
Monitor.Enter(lockObject);
try
{
// code within lock { }
}
finally
{
Monitor.Exit(lockObject);
}
I believe you are looking for the lock statement.
private readonly object _lock = new object();
private void ProccessCommand(Command command)
{
lock (_lock)
{
// ...
}
}
It sounds like you just need to use the lock statement. Code inside a lock statement will allow only one thread to work inside the code block at once.
More info: lock Statement
From the sounds of what you've posted here, you might be able to avoid so many waiting threads. You could queue up the next command to execute, and rather than keep the threads waiting, just replace the command to execute next after the current command finishes. Lock when replacing and removing the "waiting" command.
Something like this:
class CommandHandler
{
Action nextCommand;
ManualResetEvent manualResetEvent = new ManualResetEvent(false);
object lockObject = new object();
public CommandHandler()
{
new Thread(ProcessCommands).Start();
}
public void AddCommand(Action nextCommandToProcess)
{
lock (lockObject)
{
nextCommand = nextCommandToProcess;
}
manualResetEvent.Set();
}
private void ProcessCommands()
{
while (true)
{
Action action = null;
lock (lockObject)
{
action = nextCommand;
nextCommand = null;
}
if (action != null)
{
action();
}
lock (lockObject)
{
if(nextCommand != null)
continue;
manualResetEvent.Reset();
}
manualResetEvent.WaitOne();
}
}
}
check out: ManualResetEvent
It's a useful threading class.