what's wrong with my producer-consumer queue design? - c#

I'm starting with the C# code example here. I'm trying to adapt it for a couple reasons: 1) in my scenario, all tasks will be put in the queue up-front before consumers will start, and 2) I wanted to abstract the worker into a separate class instead of having raw Thread members within the WorkerQueue class.
My queue doesn't seem to dispose of itself though, it just hangs, and when I break in Visual Studio it's stuck on the _th.Join() line for WorkerThread #1. Also, is there a better way to organize this? Something about exposing the WaitOne() and Join() methods seems wrong, but I couldn't think of an appropriate way to let the WorkerThread interact with the queue.
Also, an aside - if I call q.Start(#) at the top of the using block, only some of the threads every kick in (e.g. threads 1, 2, and 8 process every task). Why is this? Is it a race condition of some sort, or am I doing something wrong?
using System;
using System.Collections.Generic;
using System.Text;
using System.Messaging;
using System.Threading;
using System.Linq;
namespace QueueTest
{
class Program
{
static void Main(string[] args)
{
using (WorkQueue q = new WorkQueue())
{
q.Finished += new Action(delegate { Console.WriteLine("All jobs finished"); });
Random r = new Random();
foreach (int i in Enumerable.Range(1, 10))
q.Enqueue(r.Next(100, 500));
Console.WriteLine("All jobs queued");
q.Start(8);
}
}
}
class WorkQueue : IDisposable
{
private Queue<int> _jobs = new Queue<int>();
private int _job_count;
private EventWaitHandle _wh = new AutoResetEvent(false);
private object _lock = new object();
private List<WorkerThread> _th;
public event Action Finished;
public WorkQueue()
{
}
public void Start(int num_threads)
{
_job_count = _jobs.Count;
_th = new List<WorkerThread>(num_threads);
foreach (int i in Enumerable.Range(1, num_threads))
{
_th.Add(new WorkerThread(i, this));
_th[_th.Count - 1].JobFinished += new Action<int>(WorkQueue_JobFinished);
}
}
void WorkQueue_JobFinished(int obj)
{
lock (_lock)
{
_job_count--;
if (_job_count == 0 && Finished != null)
Finished();
}
}
public void Enqueue(int job)
{
lock (_lock)
_jobs.Enqueue(job);
_wh.Set();
}
public void Dispose()
{
Enqueue(Int32.MinValue);
_th.ForEach(th => th.Join());
_wh.Close();
}
public int GetNextJob()
{
lock (_lock)
{
if (_jobs.Count > 0)
return _jobs.Dequeue();
else
return Int32.MinValue;
}
}
public void WaitOne()
{
_wh.WaitOne();
}
}
class WorkerThread
{
private Thread _th;
private WorkQueue _q;
private int _i;
public event Action<int> JobFinished;
public WorkerThread(int i, WorkQueue q)
{
_i = i;
_q = q;
_th = new Thread(DoWork);
_th.Start();
}
public void Join()
{
_th.Join();
}
private void DoWork()
{
while (true)
{
int job = _q.GetNextJob();
if (job != Int32.MinValue)
{
Console.WriteLine("Thread {0} Got job {1}", _i, job);
Thread.Sleep(job * 10); // in reality would to actual work here
if (JobFinished != null)
JobFinished(job);
}
else
{
Console.WriteLine("Thread {0} no job available", _i);
_q.WaitOne();
}
}
}
}
}

The worker threads are all blocking on the _q.WaitOne() call in DoWork(). Calling the thread's Join() method will deadlock, the threads never exit. You'll need to add a mechanism to signal to worker thread to exit. A ManualResetEvent, tested with WaitAny in the worker, will get the job done.
One debugging tip: get familiar with the Debug + Windows + Threads window. It lets you switch between threads and look at their call stacks. You'd have quickly found this problem by yourself.

You do a WaitOne() at the end of DoWork but you never set it after the threads start running.
Note that AutoResetEvent will go back to not set state after a 'successful' WaitOne

Your loop in your DoWork method never finishes. This will cause the thread to always be busy and this thread.Join() will block forever, waiting for it to complete.
You have a WaitOne, but I don't think it's necessary unless there is a reason you want your threadpool to stick around after your work is complete:
private void DoWork()
{
bool done = false;
while (!done)
{
int job = _q.GetNextJob();
if (job != Int32.MinValue)
{
Console.WriteLine("Thread {0} Got job {1}", _i, job);
Thread.Sleep(job * 10); // in reality would to actual work here
if (JobFinished != null)
JobFinished(job);
}
else
{
Console.WriteLine("Thread {0} no job available", _i);
done = true;
}
}
}
If you want the threads to stick around so you don't have to realloc more threads when WorkQueue.Start is called, you'd have to do something more elaborate with the AutoResetEvent.

Your main problem is the deterministic deadlock described in the other answers.
The correct way to handle it, though, is not to fix the deadlock, but to eliminate the Event altogether.
The whole idea of the Producer-Consumer model is that the clients En-queue and De-queue elements concurrently, and that's why sync mechanisms are required. If you're enqueuing all of the elements beforehand and then only dequeue concurrently, you only need a lock on the dequeue, since the "Event" is used to let "Consumers" wait for new elements to be enqueued; this will not happen in your case (based on your description).
Also, the "single responsibility" design principle suggests that the threading code should be separated from the "Blocking Queue" code. Make the "Blocking Queue" a class of its own, then use it in your thread-management class.

Related

Producer/Consumer Thread Pool w/ Main Thread Support - Infrequent Deadlock?

I have a C# thread pool class that is based heavily on the producer/consumer code from https://stackoverflow.com/a/1656662/782181. NOTE: I'm doing this instead of using BlockingCollection because I'm stuck with .NET2.0!
I added a function to the class that can be called from the main thread to allow the main thread to do some work. My thinking here was that, at some point, the main thread waits for work to be done, but instead of waiting, I could also have the main thread do some of the work to speed things up.
Here's a slimmed version of the class to demonstrate:
public static class SGThreadPool
{
// Shared object to lock access to the queue between threads.
private static object locker = new object();
// The various threads that are doing our work.
private static List<Thread> workers = null;
// A queue of tasks to be completed by the workers.
private static Queue<object> taskQueue = new Queue<object>();
private static Queue<WaitCallback> taskCallbacks = new Queue<WaitCallback>();
//OMMITTED: Init function (starts threads)
// Enqueues a task for a thread to do.
public static void EnqueueTask(WaitCallback callback, object context)
{
lock(locker)
{
taskQueue.Enqueue(context);
taskCallbacks.Enqueue(callback);
Monitor.PulseAll(locker); //Q: should I just use 'Pulse' here?
}
}
// Can be called from main thread to have it "help out" with tasks.
public static bool PerformTask()
{
WaitCallback taskCallback = null;
object task = null;
lock(locker)
{
if(taskQueue.Count > 0)
{
task = taskQueue.Dequeue();
}
if(taskCallbacks.Count > 0)
{
taskCallback = taskCallbacks.Dequeue();
}
}
// No task means no work, return false.
if(task == null || taskCallback == null) { return false; }
// Do the work!
taskCallback(task);
return true;
}
private static void Consume()
{
while(true)
{
WaitCallback taskCallback = null;
object task = null;
lock(locker)
{
// While no tasks in the queue, wait.
while(taskQueue.Count == 0)
{
Monitor.Wait(locker);
}
// Get a task.
task = taskQueue.Dequeue();
taskCallback = taskCallbacks.Dequeue();
}
// Null task signals an exit.
if(task == null || taskCallback == null) { return; }
// Call consume callback with task as context.
taskCallback(task);
}
}
}
Basically, I can enqueue a number of tasks to be performed by background threads. But it is also possible for the main thread to take a task and perform it by calling PerformTask().
I'm running into an infrequent problem where the main thread will try to "lock" in PerformTask(), but the lock is already taken. The main thread waits, but the lock doesn't ever become available, for some reason.
Nothing in the code is jumping out at me as a problem causing the deadlock - I'm hoping that someone else might be able to spot the problem. I've been looking at this for a couple hours, and I'm not sure why the main thread would get stuck at the "lock()" call in PerformTask(). It seems like no other thread would be holding the lock indefinitely? Is it a bad idea to allow the main thread to interact with the pool in this way?
Hmm, so, while I would still like to know why the code above could deadlock in certain scenarios, I think I've found a workaround that will do the trick.
If the main thread is going to be doing work here, I want to make sure the main thread doesn't get blocked for a long period of time. After all, a general dev rule: don't block the main thread!
So, the solution I'm trying is to use Monitor.TryEnter directly, rather than using lock() for the main thread. This allows me to specify a timeout for how long the main thread is willing to wait for the lock.
public static bool PerformTask()
{
WaitCallback taskCallback = null;
object task = null;
// Use TryEnter, rather than "lock" because
// it allows us to specify a timeout as a failsafe.
if(Monitor.TryEnter(locker, 500))
{
try
{
// Pull a task from the queue.
if(taskQueue.Count > 0)
{
task = taskQueue.Dequeue();
}
if(taskCallbacks.Count > 0)
{
taskCallback = taskCallbacks.Dequeue();
}
}
finally
{
Monitor.Exit(locker);
}
}
// No task means no work, return false.
if(task == null || taskCallback == null) { return false; }
// Do the work!
taskCallback(task);
return true;
}
In this code, the thread will wait to acquire the lock for up to 500ms. If it can't for whatever reason, it fails to do any tasks, but at least it doesn't get stuck. It seems like a good idea to not put the main thread in a position where it could wait indefinitely.
I believe that when you use lock(), the compiler generates similar code anyways, so I don't think there would be any performance issue with this solution.

How to stop task(thread) and release in other task? [duplicate]

Hi guys I start threads with such code:
Thread[] thr;
private void button1_Click(object sender, EventArgs e)
{
decimal value = numericUpDown2.Value;
int i = 0;
threads_count = (int)(value);
thr = new Thread[threads_count];
for (; i < threads_count; i++)
{
thr[i] = new Thread(new ThreadStart(go));
thr[i].IsBackground = true;
thr[i].Start();
}
}
How to stop all them if my condition become true
A number of the answers say to abort the thread. Never abort a thread unless it is an emergency situation and you are shutting down the application.
The CLR guarantees that its internal data structures are not corrupted by a thread abort. This is the only (*) guarantee made by the CLR with respect to thread aborts. It specifically does not guarantee:
That the thread actually will abort. Threads can harden themselves against being terminated.
That any data structure that is not in the CLR itself will be uncorrupted. Thread aborts in the middle of crucial operations can leave BCL data structures or user data structures in arbitrarily inconsistent states. This can crash your process mysteriously later.
That locks will be released. Aborting threads can cause locks to be held forever, it can cause deadlocks, and so on.
In case I am not being clear: it is insanely dangerous to abort a thread and you should only do so when all the alternatives are worse.
So what if you want to start up a thread and then shut it down cleanly?
First, don't do that. Don't start a thread in the first place. Start a Task<T> with a cancellation token and when you want to shut it down, signal its cancellation token.
If you do have to start a thread, then start the thread such that there is some mechanism whereby the main thread and the working thread can cleanly and safely communicate "I want you to shut yourself down cleanly at this time".
If you don't know how to do that then stop writing multithreaded code until you learn how to do that.
(*) This is a small lie; the CLR also makes certain guarantees with respect to the interactions of thread aborts and special code regions such as constrained execution regions and finally blocks.
You can use a CancellationToken to signal when the operation should stop.
Create a CancellationTokenSource as an instance field of your type that you initialize in the button click handler.
In your background method periodically check the IsCancellationRequested property of the Token in the token source, or call ThrowIfCancellationRequested() if you want it to just throw an exception if it is canceled.
When you want to stop the threads call Cancel on the token source.
Brutal way (not recommended) - use Thread.Abort method to abort threads. This method raises ThreadAbortException on thread. Like this:
foreach(Thread thread in thr)
thread.Abort();
But better way is notifying thread about cancellation and letting it correctly finish its job. You can do it simply with .Net 4 tasks:
Task[] thr = new Task[threads_count];
var source = new CancellationTokenSource();
for (int i = 0; i < threads_count; i++)
{
thr[i] = Task.Factory.StartNew(go, source.Token);
}
// later, when condition is met
source.Cancel();
And here is how cancellation should look like:
private static void go(object obj)
{
CancellationToken token = (CancellationToken)obj;
while (true)
{
if (token.IsCancellationRequested)
return;
// do some work
}
}
If you want to know how to terminate the thread gracefully, I'd recommend you to take a look the following example on MSDN:
using System;
using System.Threading;
public class Worker
{
public void DoWork()
{
while (!_shouldStop)
{
Console.WriteLine("worker thread: working...");
}
Console.WriteLine("worker thread: terminating gracefully.");
}
public void RequestStop()
{
_shouldStop = true;
}
// Volatile is used as hint to the compiler that this data
// member will be accessed by multiple threads.
private volatile bool _shouldStop;
}
public class WorkerThreadExample
{
static void Main()
{
Worker workerObject = new Worker();
Thread workerThread = new Thread(workerObject.DoWork);
workerThread.Start();
Console.WriteLine("main thread: Starting worker thread...");
while (!workerThread.IsAlive); // Loop until worker thread activates
// Put the main thread to sleep for 1 millisecond to
// allow the worker thread to do some work:
Thread.Sleep(1);
workerObject.RequestStop();
// Use the Join method to block the current thread
// until the object's thread terminates.
workerThread.Join();
Console.WriteLine("main thread: Worker thread has terminated.");
}
}
This is Windows Form Code in which:
1) On Clicking start button, Main Thread creates another Thread
2) Again created Thread creates on more Thread.
3) On clicking Stop button, First the last Thread should terminate Then the Thread created by Main thread should Terminate.
namespace Thread_TerminateProblem
{
public partial class Form1 : Form
{
private static AutoResetEvent m_ResetEvent = null;
private static ManualResetEvent m_ResetEvent_Thread = new ManualResetEvent(false);
enum ServiceState { Start, Stop };
bool flag = false;
int x = 0;
ServiceState _state;
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
flag = true;
_state = ServiceState.Start;
m_ResetEvent = new AutoResetEvent(true);
Thread t1 = new Thread(fun_Thread1);
t1.Start();
t1.Name = "Thread1";
}
private void btnStop_Click(object sender, EventArgs e)
{
_state = ServiceState.Stop;
m_ResetEvent.Set();
}
private void fun_Thread1()
{
while (true)
{
m_ResetEvent.WaitOne();
switch (_state)
{
case ServiceState.Start:
{
Thread t = new Thread(fun_Thread2);
t.Start();
t.Name = "Thread2";
break;
}
case ServiceState.Stop:
{
m_ResetEvent_Thread.Set();
flag = true;
break;
}
}
// When the child Thread terminates, Then only this thread should terminate
if (flag == true)
{
// Waiting for notification from child Thread
notifyParent.WaitOne();
Thread.Sleep(100);
break;
}
m_ResetEvent.Reset();
}
}
private static ManualResetEvent notifyParent = new ManualResetEvent(false);
private void fun_Thread2()
{
while (true)
{
if (m_ResetEvent_Thread.WaitOne(1, false))
{
notifyParent.Set();
break;
}
x++;
}
}
}
}
simplistic answer is to use the thread Abort() method however your code does not really make it clear what condition,
what loop tests vs a condition? why do you need to abort a thread? I am asking as there may be a better way to approach this

How to ensure run of a thread exactly after end of running of a specifc number of other threads?

I have a class in C# like this:
public MyClass
{
public void Start() { ... }
public void Method_01() { ... }
public void Method_02() { ... }
public void Method_03() { ... }
}
When I call the "Start()" method, an external class start to work and will create many parallel threads that those parallel threads call the "Method_01()" and "Method_02()" form above class. after end of working of the external class, the "Method_03()" will be run in another parallel thread.
Threads of "Method_01()" or "Method_02()" are created before creation of thread of Method_03(), but there is no guaranty to end before start of thread of "Method_03()". I mean the "Method_01()" or the "Method_02()" will lost their CPU turn and the "Method_03" will get the CPU turn and will end completely.
In the "Start()" method I know the total number of threads that are supposed to create and run "Method_01" and "Method_02()". The question is that I'm searching for a way using semaphore or mutex to ensure that the first statement of "Method_03()" will be run exactly after end of all threads which are running "Method_01()" or "Method_02()".
Three options that come to mind are:
Keep an array of Thread instances and call Join on all of them from Method_03.
Use a single CountdownEvent instance and call Wait from Method_03.
Allocate one ManualResetEvent for each Method_01 or Method_02 call and call WaitHandle.WaitAll on all of them from Method_03 (this is not very scalable).
I prefer to use a CountdownEvent because it is a lot more versatile and is still super scalable.
public class MyClass
{
private CountdownEvent m_Finished = new CountdownEvent(0);
public void Start()
{
m_Finished.AddCount(); // Increment to indicate that this thread is active.
for (int i = 0; i < NUMBER_OF_THREADS; i++)
{
m_Finished.AddCount(); // Increment to indicate another active thread.
new Thread(Method_01).Start();
}
for (int i = 0; i < NUMBER_OF_THREADS; i++)
{
m_Finished.AddCount(); // Increment to indicate another active thread.
new Thread(Method_02).Start();
}
new Thread(Method_03).Start();
m_Finished.Signal(); // Signal to indicate that this thread is done.
}
private void Method_01()
{
try
{
// Add your logic here.
}
finally
{
m_Finished.Signal(); // Signal to indicate that this thread is done.
}
}
private void Method_02()
{
try
{
// Add your logic here.
}
finally
{
m_Finished.Signal(); // Signal to indicate that this thread is done.
}
}
private void Method_03()
{
m_Finished.Wait(); // Wait for all signals.
// Add your logic here.
}
}
This appears to be a perfect job for Tasks. Below I assume that Method01 and Method02 are allowed to run concurrently with no specific order of invocation or finishing (with no guarantee, just typed in out of memory without testing):
int cTaskNumber01 = 3, cTaskNumber02 = 5;
Task tMaster = new Task(() => {
for (int tI = 0; tI < cTaskNumber01; ++tI)
new Task(Method01, TaskCreationOptions.AttachedToParent).Start();
for (int tI = 0; tI < cTaskNumber02; ++tI)
new Task(Method02, TaskCreationOptions.AttachedToParent).Start();
});
// after master and its children are finished, Method03 is invoked
tMaster.ContinueWith(Method03);
// let it go...
tMaster.Start();
What it sounds like you need to do is to create a ManualResetEvent (initialized to unset) or some other WatHandle for each of Method_01 and Method_02, and then have Method_03's thread use WaitHandle.WaitAll on the set of handles.
Alternatively, if you can reference the Thread variables used to run Method_01 and Method_02, you could have Method_03's thread use Thread.Join to wait on both. This assumes however that those threads are actually terminated when they complete execution of Method_01 and Method_02- if they are not, you need to resort to the first solution I mention.
Why not use a static variable static volatile int threadRuns, which is initialized with the number threads Method_01 and Method_02 will be run.
Then you modify each of those two methods to decrement threadRuns just before exit:
...
lock(typeof(MyClass)) {
--threadRuns;
}
...
Then in the beginning of Method_03 you wait until threadRuns is 0 and then proceed:
while(threadRuns != 0)
Thread.Sleep(10);
Did I understand the quesiton correctly?
There is actually an alternative in the Barrier class that is new in .Net 4.0. This simplifies the how you can do the signalling across multiple threads.
You could do something like the following code, but this is mostly useful when synchronizing different processing threads.
public class Synchro
{
private Barrier _barrier;
public void Start(int numThreads)
{
_barrier = new Barrier((numThreads * 2)+1);
for (int i = 0; i < numThreads; i++)
{
new Thread(Method1).Start();
new Thread(Method2).Start();
}
new Thread(Method3).Start();
}
public void Method1()
{
//Do some work
_barrier.SignalAndWait();
}
public void Method2()
{
//Do some other work.
_barrier.SignalAndWait();
}
public void Method3()
{
_barrier.SignalAndWait();
//Do some other cleanup work.
}
}
I would also like to suggest that since your problem statement was quite abstract, that often actual problems that are solved using countdownevent are now better solved using the new Parallel or PLINQ capabilities. If you were actually processing a collection or something in your code, you might have something like the following.
public class Synchro
{
public void Start(List<someClass> collection)
{
new Thread(()=>Method3(collection));
}
public void Method1(someClass)
{
//Do some work.
}
public void Method2(someClass)
{
//Do some other work.
}
public void Method3(List<someClass> collection)
{
//Do your work on each item in Parrallel threads.
Parallel.ForEach(collection, x => { Method1(x); Method2(x); });
//Do some work on the total collection like sorting or whatever.
}
}

Queueing Operation

im sending smses using dll, that dll have some events one them is
Session_OnMessageAccepted
inside that im doing something like this
void Session_OnMessageAccepted(object sender,EventArgs e)
{
new Thread(
delegate()
{
//do stuff
}).Start();
}
this is ok only problem is the code inside dostuff gets excuted same time , is there is any chance i can put "dostuff"in a queue and make it happen synchronously?
You're looking for the ConcurrentQueue class.
You can add the messages in the queue. And you can have a separate thread started(On App Start) which will continuously look for messages in the queue and process it.
i.e in the thread method
while(true)
{
//check if the queue is empty otherwise continue;
//fetch the element
//process it
}
A Note About The ThreadPool
As a general comment to your current code, consider using ThreadPool.QueueUserWorkItem rather than creating new threads.
Queuing work items to the ThreadPool is much more efficient than creating new threads for short term tasks. The ThreadPool maintains a pool of existing threads and re-uses them. Creating and managing threads is expensive so should be avoided when needing many short-lived tasks. As well as being efficient, the ThreadPool also has natural queuing behaviour.
However, using the ThreadPool does not guarantee that items are executed in the order you queued them, and may also result in items being executated at the same time i.e. concurrently. Therefore the ThreadPool doesn't help you out for this particular quesiton.
Example Message Processing Loop
The following is a message processing loop pattern which allows operations to be queued and then processing on a separate thread serially.
public class SomeClass
{
private readonly object _syncObj = new object();
private readonly Thread _thread;
private readonly Queue<Action> _queue = new Queue<Action>();
private readonly ManualResetEvent _messageAccepted = new ManualResetEvent(false);
public SomeClass()
{
_thread = new Thread(() =>
{
while (true)
{
Action operation;
while (TryDequeue(out operation))
{
operation();
}
_messageAccepted.WaitOne();
}
}) {IsBackground = true};
_thread.Start();
}
private void Session_OnMessageAccepted(object sender, EventArgs e)
{
Action operation = () =>{/* Do stuff */};
Enqueue(operation);
}
private void Enqueue(Action operation)
{
lock (_syncObj)
{
_queue.Enqueue(operation);
_messageAccepted.Set();
}
}
private bool TryDequeue(out Action operation)
{
lock (_syncObj)
{
operation = (_queue.Count != 0) ? _queue.Dequeue() : null;
if (operation == null) _messageAccepted.Reset();
return (operation != null);
}
}
}

BlockingCollection class: Does thread yield if Take blocks?

MSDN said that BlockingCollection.Take call blocks if there is no elements in it. Does it mean the thread will yield the timeslice and go to the waiting threads queue?
If yes does it mean that the thread will change its state to Ready once the blocking collection received an item and then will be scheduled to next timeslice as per usual rules?
Yes. When you call Take() on a BlockingCollection<T>, the thread will sit blocked (waiting on an event handle) until an element is added to the collection from another thread. This will cause that thread to give up its time slice.
When an element is added to the collection, the thread will get signaled to continue, get the element, and continue on.
I thought this might be interesting for further readers. This is how I established this for fact.
class Program
{
static BlockingCollection<int> queue = new BlockingCollection<int>();
static Thread th = new Thread(ThreadMethod);
static Thread th1 = new Thread(CheckMethod);
static void Main(string[] args)
{
th.Start();
th1.Start();
for (int i = 0; i < 100; i++)
{
queue.Add(i);
Thread.Sleep(100);
}
th.Join();
Console.ReadLine();
}
static void ThreadMethod()
{
while (!queue.IsCompleted)
{
int r = queue.Take();
Console.WriteLine(r);
}
}
static void CheckMethod()
{
while (!queue.IsCompleted)
{
Console.WriteLine(th.ThreadState);
Thread.Sleep(48);
}
}
}

Categories