Threading only block the first thread (Attempt Two) - c#

I have asked this question before - but I have spent some time thinking about it and have implemented a working version.
Overview
1) Threads are being created to perform a certain task.
2) Only one thread can perform the task at a time.
3) Each thread performs the exact same task. (Does a bunch of checks and validations on a system)
3) The threads are being created faster than the task can be performed. (I have no control over the thread creation)
Result is that overtime I get a backlog of threads to perform the task.
What I have implemented goes as follows
1) Thread checks to see how many active threads there are.
2) If there are 0 threads it is marked to PerformTask and it starts the task
3) If there is 1 thread it is marked to PerformTak and it blocks
4) If there is more than 1 thread the thread is not marked to PerformTasks and just dies
The idea is that if there is a thread waiting to perform the task already I just kill the thread.
Here is the code that I came up with
bool tvPerformTask = false;
ivNumberOfProcessesSemaphore.WaitOne();
if (ivNumberOfProcessesWaiting == 0 ||
ivNumberOfProcessesWaiting == 1)
{
ivNumberOfProcessesWaiting++;
tvPerformTask = true;
}
ivNumberOfProcessesSemaphore.Release();
if (tvPerformTask)
{
//Here we perform the work
ivProcessSemaphore.WaitOne();
//Thread save
ivProcessSemaphore.Release();
ivNumberOfProcessesSemaphore.WaitOne();
ivNumberOfProcessesWaiting--;
ivNumberOfProcessesSemaphore.Release();
}
else
{
//we just let the thread die
}
The problem that I have is not that it doesn't work it is just that I do not find the code elegant specifically I am not very happy that I need 2 semaphores an integer and a local flag to control it all. If there a way to implement this or pattern that would make the code simpler.

How about this?
private readonly _lock = new object();
private readonly _semaphore = new Semaphore(2, 2);
private void DoWork()
{
if (_semaphore.WaitOne(0))
{
try
{
lock (_lock)
{
// ...
}
}
finally
{
_semaphore.Release();
}
}
}

Consider using a ThreadPool instead of trying to managing the creation and destruction of individual threads on your own.

Related

Better approach to concurrently "do or wait and skip"

I wonder is there a better solution for this task. One have a function which called concurrently by some amount of threads, but if some thread is already executing the code the other threads should skip that part of code and wait until that thread finish the execution. Here is what I have for now:
int _flag = 0;
readonly ManualResetEventSlim Mre = new ManualResetEventSlim();
void Foo()
{
if (Interlocked.CompareExchange(ref _flag, 1, 0) == 0)
{
Mre.Reset();
try
{
// do stuff
}
finally
{
Mre.Set();
Interlocked.Exchange(ref _flag, 0);
}
}
else
{
Mre.Wait();
}
}
What I want to achieve is faster execution, lower overhead and prettier look.
You could use a combination of an AutoResetEvent and a Barrier to do this.
You can use the AutoResetEvent to ensure that only one thread enters a "work" method.
The Barrier is used to ensure that all the threads wait until the one that entered the "work" method has returned from it.
Here's some sample code:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Demo
{
class Program
{
const int TASK_COUNT = 3;
static readonly Barrier barrier = new Barrier(TASK_COUNT);
static readonly AutoResetEvent gate = new AutoResetEvent(true);
static void Main()
{
Parallel.Invoke(task, task, task);
}
static void task()
{
while (true)
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " is waiting at the gate.");
// This bool is just for test purposes to prevent the same thread from doing the
// work every time!
bool didWork = false;
if (gate.WaitOne(0))
{
work();
didWork = true;
gate.Set();
}
Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " is waiting at the barrier.");
barrier.SignalAndWait();
if (didWork)
Thread.Sleep(10); // Give a different thread a chance to get past the gate!
}
}
static void work()
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " is entering work()");
Thread.Sleep(3000);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " is leaving work()");
}
}
}
However, it might well be that the Task Parallel Library might have a better, higher-level solution. It's worth reading up on it a bit.
First of all, the waiting threads wouldn't do anything, they only wait, and after they get the signal from the event, they simply move out of the method, so you should add the while loop. After that, you can use the AutoResetEvent instead of manual one, as #MatthewWatson suggested. Also, you may consider SpinWait inside the loop, which is a lightweight solution.
Second, why use int, if this is definitely bool nature for the flag field?
Third, why not to use the simple locking, as #grrrrrrrrrrrrr suggested? This is exactly what are you doing here: forcing other threads to wait for one. If your code should write something by only one thread in a given time, but can read by multiple threads, you can use the ReaderWriterLockSlim object for such synchronization.
What I want to achieve is faster execution, lower overhead and prettier look.
faster execution
unless your "Do Stuff" is extremely fast this code shouldn't have any major overhead.
lower overhead
Again, Interlocked Exchange,/CompareExchange are very low overhead, as is manual reset event.
If your "Do Stuff" is really fast, e.g. moving a linked list head, then you can spin:
prettier look
Correct multi-threaded C# code rarely looks pretty when compared to correct single threaded C# code. The language idioms are just not there yet.
That said: If you have a really fast operation ("a few tens of cycles"), then you can spin: (although without knowing exactly what your code is doing, I can't say if this is correct).
if (Interlocked.CompareExchange(ref _flag, 1, 0) == 0)
{
try
{
// do stuff that is very quick.
}
finally
{
Interlocked.Exchange(ref _flag, 0);
}
}
else
{
SpinWait.SpinUntil(() => _flag == 0);
}
The first thing that springs to mind is to change it to use a lock. This won't skip the code, but will cause each thread getting to it to pause while the first thread executes its stuff. This way the lock will also automatically get released in the case of an exception.
object syncer = new object();
void Foo()
{
lock(syncer)
{
//Do stuff
}
}

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.

c# event handling: best practice to avoid thread contention and threadpool draining

When events trigger, they use threads from the threadpool. So if you have a bunch of events that trigger faster than they return, you drain your threadpool. So whenever you have an event handler method that doesn't have any other control to limit the rate of threads entering, and doesn't have any guarantee of returning quickly, and you're not painstakingly implementing 100% thread-safe code inside that method, it's probably best to implement some thread control. The obvious simple thing to do would be to lock() inside the event handling method, but if you do that, all the threads after the first one will block in queue, waiting to enter the lock region, hogging all your threads from threadpool. It is probably better to detect another thread is inside this method, and quickly abort instead.
The question is: I have a way of detecting another thread already running, and quickly aborting the subsequent threads. But it doesn't seem very C#-ish due to the use of "const" and manually handling a locking flag at a low level. Is there a better way?
This is basically a direct replication of the lock() functionality, but using a non-blocking Interlocked.Exchange, instead of using the blocking Monitor.Enter()
public class FooGoo
{
private const int LOCKED = 0; // could use any arbitrary value; I choose 0
private const int UNLOCKED = LOCKED + 1; // any arbitrary value, != LOCKED
private static int _myLock = UNLOCKED;
void myEventHandler()
{
int previousValue = Interlocked.Exchange(ref _myLock, LOCKED);
if ( previousValue == UNLOCKED )
{
try
{
// some handling code, which may or may not return quickly
// maybe not threadsafe
}
finally
{
_myLock = UNLOCKED;
}
}
else
{
// another thread is executing right now. So I will abort.
//
// optional and environment-specific, maybe you want to
// queue some event information or set a flag or something,
// so you remember later that this thread aborted
}
}
}
So far, this is the best answer I have found. Does there exist any shorthand equivalent of a non-blocking lock() to shorten this up?
static object _myLock;
void myMethod ()
{
if ( Monitor.TryEnter(_myLock) )
{
try
{
// Do stuff
}
finally
{
Monitor.Exit(_myLock);
}
}
else
{
// then I failed to get the lock. Optionally do stuff.
}
}

What's a useful pattern for waiting for all threads to finish?

I have a scenario where I will have to kick off a ton of threads (possibly up to a 100), then wait for them to finish, then perform a task (on yet another thread).
What is an accepted pattern for doing this type of work? Is it simply .Join? Or is there a higher level of abstraction nowadays?
Using .NET 2.0 with VS2008.
In .NET 3.5sp1 or .NET 4, the TPL would make this much easier. However, I'll tailor this to .NET 2 features only.
There are a couple of options. Using Thread.Join is perfectly acceptable, especially if the threads are all ones you are creating manually. This is very easy, reliable, and simple to implement. It would probably be my choice.
However, the other option would be to create a counter for the total amount of work, and to use a reset event when the counter reaches zero. For example:
class MyClass {
int workToComplete; // Total number of elements
ManualResetEvent mre; // For waiting
void StartThreads()
{
this.workToComplete = 100;
mre = new ManualResetEvent(false);
int total = workToComplete;
for(int i=0;i<total;++i)
{
Thread thread = new Thread( new ThreadStart(this.ThreadFunction) );
thread.Start(); // Kick off the thread
}
mre.WaitOne(); // Will block until all work is done
}
void ThreadFunction()
{
// Do your work
if (Interlocked.Decrement(ref this.workToComplete) == 0)
this.mre.Set(); // Allow the main thread to continue here...
}
}
Did you look at ThreadPool? Looks like here -ThreadPool tutorial, avtor solves same task as you ask.
What's worked well for me is to store each thread's ManagedThreadId in a dictionary as I launch it, and then have each thread pass its id back through a callback method when it completes. The callback method deletes the id from the dictionary and checks the dictionary's Count property; when it's zero you're done. Be sure to lock around the dictionary both for adding to and deleting from it.
I am not sure that any kind of standard thread locking or synchronization mechanisms will really work with so many threads. However, this might be a scenario where some basic messaging might be an ideal solution to the problem.
Rather than using Thread.Join, which will block (and could be very difficult to manage with so many threads), you might try setting up one more thread that aggregates completion messages from your worker threads. When the aggregator has received all expected messages, it completes. You could then use a single WaitHandle between the aggregator and your main application thread to signal that all of your worker threads are done.
public class WorkerAggregator
{
public WorkerAggregator(WaitHandle completionEvent)
{
m_completionEvent = completionEvent;
m_workers = new Dictionary<int, Thread>();
}
private readonly WaitHandle m_completionEvent;
private readonly Dictionary<int, Thread> m_workers;
public void StartWorker(Action worker)
{
var thread = new Thread(d =>
{
worker();
notifyComplete(thread.ManagedThreadID);
}
);
lock (m_workers)
{
m_workers.Add(thread.ManagedThreadID, thread);
}
thread.Start();
}
private void notifyComplete(int threadID)
{
bool done = false;
lock (m_workers)
{
m_workers.Remove(threadID);
done = m_workers.Count == 0;
}
if (done) m_completionEvent.Set();
}
}
Note, I have not tested the code above, so it might not be 100% correct. However I hope it illustrates the concept enough to be useful.

ManualResetEvent vs. Thread.Sleep

I implemented the following background processing thread, where Jobs is a Queue<T>:
static void WorkThread()
{
while (working)
{
var job;
lock (Jobs)
{
if (Jobs.Count > 0)
job = Jobs.Dequeue();
}
if (job == null)
{
Thread.Sleep(1);
}
else
{
// [snip]: Process job.
}
}
}
This produced a noticable delay between when the jobs were being entered and when they were actually starting to be run (batches of jobs are entered at once, and each job is only [relatively] small.) The delay wasn't a huge deal, but I got to thinking about the problem, and made the following change:
static ManualResetEvent _workerWait = new ManualResetEvent(false);
// ...
if (job == null)
{
lock (_workerWait)
{
_workerWait.Reset();
}
_workerWait.WaitOne();
}
Where the thread adding jobs now locks _workerWait and calls _workerWait.Set() when it's done adding jobs. This solution (seemingly) instantly starts processing jobs, and the delay is gone altogether.
My question is partly "Why does this happen?", granted that Thread.Sleep(int) can very well sleep for longer than you specify, and partly "How does the ManualResetEvent achieve this level of performance?".
EDIT: Since someone asked about the function that's queueing items, here it is, along with the full system as it stands at the moment.
public void RunTriggers(string data)
{
lock (this.SyncRoot)
{
this.Triggers.Sort((a, b) => { return a.Priority - b.Priority; });
foreach (Trigger trigger in this.Triggers)
{
lock (Jobs)
{
Jobs.Enqueue(new TriggerData(this, trigger, data));
_workerWait.Set();
}
}
}
}
static private ManualResetEvent _workerWait = new ManualResetEvent(false);
static void WorkThread()
{
while (working)
{
TriggerData job = null;
lock (Jobs)
{
if (Jobs.Count > 0)
job = Jobs.Dequeue();
if (job == null)
{
_workerWait.Reset();
}
}
if (job == null)
_workerWait.WaitOne();
else
{
try
{
foreach (Match m in job.Trigger.Regex.Matches(job.Data))
job.Trigger.Value.Action(job.World, m);
}
catch (Exception ex)
{
job.World.SendLineToClient("\r\n\x1B[32m -- {0} in trigger ({1}): {2}\x1B[m",
ex.GetType().ToString(), job.Trigger.Name, ex.Message);
}
}
}
}
The events are kernel primitives provided by the OS/Kernel that's designed just for this sort of things. The kernel provides a boundary upon which you can guarantee atomic operations which is important for synchronization(Some atomicity can be done in user space too with hardware support).
In short, when a thread waits on an event it's put on a waiting list for that event and marked as non-runnable.
When the event is signaled, the kernel wakes up the ones in the waiting list and marks them as runnable and they can continue to run. It's naturally a huge benefit that a thread can wake up immediately when the event is signalled, vs sleeping for a long time and recheck the condition every now and then.
Even one millisecond is a really really long time, you could have processed thousands of event in that time. Also the time resolution is traditionally 10ms, so sleeping less than 10ms usually just results in a 10ms sleep anyway. With an event, a thread can be woken up and scheduled immediately
First locking on _workerWait is pointless, an Event is a system (kernel) object designed for signaling between threads (and heavily used in the Win32 API for asynchronous operations). Therefore it is quite safe for multiple threads to set or reset it without additional synchronization.
As to your main question, need to see the logic for placing things on the queue as well, and some information on how much work is done for each job (is the worker thread spending more time processing work or on waiting for work).
Likely the best solution would be to use an object instance to lock on and use Monitor.Pulse and Monitor.Wait as a condition variable.
Edit: With a view of the code to enqueue, it appears that answer #1116297 has it right: a 1ms delay is too long to wait, given that many of the work items will be extremely quick to process.
The approach of having a mechanism to wake up the worker thread is correct (as there is no .NET concurrent queue with a blocking dequeue operation). However rather than using an event, a condition variable is going to be a little more efficient (as in non-contended cases it does not require a kernel transition):
object sync = new Object();
var queue = new Queue<TriggerData>();
public void EnqueueTriggers(IEnumerable<TriggerData> triggers) {
lock (sync) {
foreach (var t in triggers) {
queue.Enqueue(t);
}
Monitor.Pulse(sync); // Use PulseAll if there are multiple worker threads
}
}
void WorkerThread() {
while (!exit) {
TriggerData job = DequeueTrigger();
// Do work
}
}
private TriggerData DequeueTrigger() {
lock (sync) {
if (queue.Count > 0) {
return queue.Dequeue();
}
while (queue.Count == 0) {
Monitor.Wait(sync);
}
return queue.Dequeue();
}
}
Monitor.Wait will release the lock on the parameter, wait until Pulse() or PulseAll() is called against the lock, then re-enter the lock and return. Need to recheck the wait condition because some other thread could have read the item off the queue.

Categories