How can I accomplish ThreadPool.Join? - multithreading

I am writing a windows service that uses ThreadPool.QueueUserWorkItem(). Each thread is a short-lived task.
When the service is stopped, I need to make sure that all the threads that are currently executing complete. Is there some way of waiting until the queue clears itself?

You could create an event (e.g. ManualResetEvent) in each thread, and keep it in a synchronised list (using the lock construct). Set the event or remove it from the list when the task is finished.
When you want to join, you can use WaitHandle.WaitAll (MSDN documentation) to wait for all the events to be signalled.
It's a hack, but I can't see how to reduce it to anything simpler!
Edit: additionally, you could ensure that no new events get posted, then wait a couple of seconds. If they are indeed short-lived, you'll have no problem. Even simpler, but more hacky.
Finally, if it's just a short amount of time, the service won't exit until all threads have died (unless they are background threads); so if it's a short amount of time, the service control manager won't mind a second or so - you can just leave them to expire - in my experience.

The standard pattern for doing this is to use a counter which holds the number of pending work items and one ManualResetEvent that is signalled when the counter reaches zero. This is generally better than using a WaitHandle for each work item as that does not scale very well when there are a lot of simultaneous work items. Plus, some of the static WaitHandle method only accept a maximum of 64 instances anyway.
// Initialize to 1 because we are going to treat the current thread as
// a work item as well. This is to avoid a race that could occur when
// one work item gets queued and completed before the next work item
// is queued.
int count = 1;
var finished = new ManualResetEvent(false);
try
{
while (...)
{
Interlocked.Increment(ref counter);
ThreadPool.QueueUserWorkItem(
delegate(object state)
{
try
{
// Your task goes here.
}
finally
{
// Decrement the counter to indicate the work item is done.
if (Interlocked.Decrement(ref count) == 0)
{
finished.Set();
}
}
});
}
}
finally
{
// Decrement the counter to indicate the queueing thread is done.
if (Interlocked.Decrement(ref count) == 0)
{
finished.Set();
}
}
finished.WaitOne();

Related

nodejs: what's the correct way to monitor a task queue?

I know I can write a while (true) loop to monitor the queue, but it will cause the CPU 100% problem.
I can sleep some seconds inside the while (true) loop, but it's NOT efficient.
In C language, I can wait for a semaphore inside the while (true) loop. When a task added into the queue, release the semaphore so that the while (true) loop can do its job. After the queue is empty, it can set the semaphore, and wait for it.
Is there similar way to do this in Nodejs?
Imagine we have this taskQueue:
// Tasks will be added to the array randomly
const tasks = [];
Note: the taskQueue above is something completely different than the internal NodeJS micro/macro task queue, that I'm referring to throughout this post.
A way of constantly monitoring this array would be to schedule a 'micro-task' or 'macro-task' that parses the array.
As an example:
function handleTasks() {
if (tasks.length) {
// Alternatively loop and pop all the current tasks in queue
const task = tasks.pop();
// Do something with the task
}
setImmediate(handleTasks)
}
setImmediate(handleTasks)
The setImmediate function will add a task to the internal macro-task queue.
The JS micro- and macro-tasks do not block the main thread and will only be executed when the event-loop picks it off the internal micro/macro task queue.
In NodeJS there are 4 ways of scheduling a function in a non-blocking way. Which way you pick is based on how much priority you'd want to give to the function.
Ordered by highest priority first the ways to do this are:
process.nextTick(handleTask)
new Promise((resolve) => { resolve() }).then(handleTask)
setImmediate(handleTask) / setTimeout(handleTask, 0)
setTimeout(handleTask, 1) # Every timeout value bigger than 0
Be aware that executing this function with the highest priority recursively could slow down the rest of your code.
Depending on how important clearing this taskQueue is, I'd generally suggest to use setTimeout with a reasonable value (as high as you can afford) to prevent affecting performance of your application. (Same goes for any other function that schedules itself on the micro/macro task queue.)
Questions
I know I can write a while (true) loop to monitor the queue, but it
will cause the CPU 100% problem.
In JavaScript the functions cannot be preempted, meaning that their execution cannot be halted somewhere in the middle.
The consequence is that once a function start, it will have to finish before another line of code (somewhere else) can be executed.
Therefore an infinite while-loop will not work.
I can sleep some seconds inside the while (true) loop, but it's NOT
efficient.
while(true) {
await timeout(1000);
// Do sth
}
Is actually syntactic sugar for
timeout(1000).then(() => {
// Do sth
timeout(1000).then(() => {
// Do sth
// ...etc
})
})
Using await inside a loop is considered a bad-practice, but could work since it just schedules each next iteration on the micro-task queue.
In C language, I can wait for a semaphore inside the while (true) loop. When a
task added into the queue, release the semaphore so that the while
(true) loop can do its job. After the queue is empty, it can set the
semaphore, and wait for it.
There is no such thing as a semaphore in JS. Something that might achieve a similar effect could be a callback function.
Example:
function heavyLoadTask() {
// Do sth
resumeExecution = () => {
// What to do when execution is resumed
}
}
// Somewhere else the execution could be resumed like this;
if (typeof resumeExecution === "function"){
resumeExecution();
}
Recommended reading
https://javascript.info/event-loop
https://nodejs.dev/learn/understanding-process-nexttick
https://nodejs.dev/learn/understanding-setimmediate

How can I mitigate a race condition between the UI thread and a DispatcherTimer.Tick event?

I believe I have a race condition in this code sample but am unsure how to mitigate it.
My scenario is that XAsync() always runs on the UI thread. Within XAsync(), I set m_importantMemberVariable and then start a timer; there's a 1 second delay before the timer fires.
My concern is the timer's tick event calls a method on m_importantMemberVariable. However, in the 1 second interval between starting the timer and Tick firing, XAsync() could be called again and overwrite m_importantMemberVariable.
Code example:
task<void> BobViewModel::XAsync()
{
return create_task(CreateSomethingAsync())
.then([this](SomethingAsync^ aThing)
{
this->m_importantMemberVariable = aThing;
OnPropertyChanged("ImportantMemberVariable");
// Timer has 1 second delay.
this->m_myDispatcherTimer->Start();
}, task_continuation_context::use_current())
.then([activity](task<void> result)
{
// more continuations...
});
}
void BobViewModel::OnTimerTick(Object^, Object^)
{
// Stopping the timer and detaching the event handler
// so timer only fires once.
m_myDispatcherTimer->Stop();
m_myDispatcherTimer->Tick -= m_impressionTimerToken;
m_myDispatcherTimer = { 0 };
// * Possible race condition *
m_importantMemberVariable->DoImportantThing();
}
Question: Assuming I'm correct about a race condition, is there a way to mitigate it?
My understanding is the tick event would fire on the UI thread so synchronization primitives won't help (as the UI thread would already have access).
All your operations are on the UI thread, so they've already been serialized (synchronized) for you. A simple flag will suffice:
bool m_busy; // set to false in constructor
task<void> BobViewModel::XAsync()
{
if (m_busy)
return;
m_busy = true;
// the rest of your code...
}
void BobViewModel::OnTimerTick(Object^, Object^)
{
m_busy = false;
// the rest of your code...
}
Just make sure you handle any exceptions such that you set m_busy back to false if something goes horribly wrong.
The answer to this question suggests using compare_exchange_strong with a std::atomic to ensure only one thread executes a function at a time. The problems with that approach, for this question, are:
1. The DispatcherTimer Tick event fires outside of the task continuation block, and can fire after the continuation completes.
2. A constraint on this problem is for the timer to only fire once.
Some alternative solutions are:
Use compare_exchange_strong but replace DispatcherTimer with create_delayed_task
Assuming the work doesn't have to happen on the UI thread, you can use create_delayed_task to delay work within a task continuation.
task<void>
BobViewModel::UseImportantVariableAsync(
Object^ importantVariable
)
{
return create_delayed_task(
std::chrono::milliseconds(1000),
[importantVariable]()
{
importantMemberVariable->DoImportantThing();
});
}
Then, from the task continuation, simply:
return UseImportantVariableAsync(m_importantMemberVariable);
Use a lambda for the DispatcherTimer's Tick event and capture 'aThing' from the question's example (instead of referencing the member variable in the handler). To only fire the timer once, assign the DispathcerTimer.Tick handler within a std::call_once block so only the first caller gets to do it.

Skipping threads based on parameter, then returning to them later

I have a method that takes in a value and if a condition is met the action shouldn't run for 24 hours. But when it stops I want to run other threads that don't met that condition.
In this example I have 30 threads made at the beginning of the program. Once I make 5 pieces of cheese I need to stop because that's too much cheese. What would be great is if there was a place to send threads that can't be acted on until time is run out while the others are running. Task.Delay even with Wait does not seem to be effective here.
Here's me code sample:
//Stop making cheese when you have enough for the day but continue making others
public void madeEnoughToday(string cheese)
{
//Find how much cheese is made based on cheese type.
DataGridViewRow row = cheeseGV.Rows
.Cast<DataGridViewRow>()
.Where(r =>
r.Cells["Cheese"].Value.ToString().Equals(cheese))
.First();
if (row.Cells["MadeToday"].Value.Equals(row.Cells["Perday"].Value))
{
Task.Delay(30000).Wait();
}
}
When I need to pause thread execution, I use another thread (global variable, or another implementation) - call Thread.Join() method for the second instance of the thread.
Thread tPause; // global var
private void MyThreadFunc()
{
// do something
if (pauseCondition)
{
tPause=new Thread(PauseThread);
tPause.Start();
tPause.Join(); // You can specify needed milliseconds, or TimeSpan
// the subsequent code will not be executed until tPause.IsAlive == true
// IMPORTANT: if tPause == null during Join() - an exception occurs
}
}
private void PauseThread()
{
Thread.Sleep(Timeout.Infinite); // You can specify needed milliseconds, or TimeSpan
}
private void Main()
{
// any actions
Thread myThread=new Thread(MyThreadFunc);
myThread.Start();
// any actions
}
There are many ways of this realization.
If you want to continue the thread execution, you can call the Thread.Abort() method for the pause thread instance, or use the sophisticated construction of function for the pause thread.

thread synchronization: making sure function gets called in order

I'm writing a program in which I need to make sure a particular function is called is not being executed in more than one thread at a time.
Here I've written some simplified pseudocode that does exactly what is done in my real program.
mutex _enqueue_mutex;
mutex _action_mutex;
queue _queue;
bool _executing_queue;
// called in multiple threads, possibly simultaneously
do_action() {
_enqueue_mutex.lock()
object o;
_queue.enqueue(o);
_enqueue_mutex.unlock();
execute_queue();
}
execute_queue() {
if (!executing_queue) {
_executing_queue = true;
enqueue_mutex.lock();
bool is_empty = _queue.isEmpty();
_enqueue_mutex.lock();
while (!is_empty) {
_action_mutex.lock();
_enqueue_mutex.lock();
object o = _queue.dequeue();
is_empty = _queue.isEmpty();
_enqueue_mutex.unlock();
// callback is called when "o" is done being used by "do_stuff_to_object_with_callback" also, this function doesn't block, it is executed on its own thread (hence the need for the callback to know when it's done)
do_stuff_to_object_with_callback(o, &some_callback);
}
_executing_queue = false;
}
}
some_callback() {
_action_mutex.unlock();
}
Essentially, the idea is that _action_mutex is locked in the while loop (I should say that lock is assumed to be blocking until it can be locked again), and expected to be unlocked when the completion callback is called (some_callback in the above code).
This, does not seem to be working though. What happens is if the do_action is called more than once at the same time, the program locks up. I think it might be related to the while loop executing more than once simultaneously, but I just cant see how that could be the case. Is there something wrong with my approach? Is there a better approach?
Thanks
A queue that is not specifically designed to be multithreaded (multi-producer multi-consumer) will need to serialize both eneueue and dequeue operations using the same mutex.
(If your queue implementation has a different assumption, please state it in your question.)
The check for _queue.isEmpty() will also need to be protected, if the dequeue operation is prone to the Time of check to time of use problem.
That is, the line
object o = _queue.dequeue();
needs to be surrounded by _enqueue_mutex.lock(); and _enqueue_mutex.unlock(); as well.
You probably only need a single mutex for the queue. Also once you've dequeued the object, you can probably process it outside of the lock. This will prevent calls to do_action() from hanging too long.
mutex moo;
queue qoo;
bool keepRunning = true;
do_action():
{
moo.lock();
qoo.enqueue(something);
moo.unlock(); // really need try-finally to make sure,
// but don't know which language we are using
}
process_queue():
{
while(keepRunning)
{
moo.lock()
if(!qoo.isEmpty)
object o = qoo.dequeue();
moo.unlock(); // again, try finally needed
haveFunWith(o);
sleep(50);
}
}
Then Call process_queue() on it's own thread.

Efficient consumer thread with multiple producers

I am trying to make a producer/consumer thread situation more efficient by skipping expensive event operations if necessary with something like:
//cas(variable, compare, set) is atomic compare and swap
//queue is already lock free
running = false
// dd item to queue – producer thread(s)
if(cas(running, false, true))
{
// We effectively obtained a lock on signalling the event
add_to_queue()
signal_event()
}
else
{
// Most of the time if things are busy we should not be signalling the event
add_to_queue()
if(cas(running, false, true))
signal_event()
}
...
// Process queue, single consumer thread
reset_event()
while(1)
{
wait_for_auto_reset_event() // Preferably IOCP
for(int i = 0; i &lt SpinCount; ++i)
process_queue()
cas(running, true, false)
if(queue_not_empty())
if(cas(running, false, true))
signal_event()
}
Obviously trying to get these things correct is a little tricky(!) so is the above pseudo code correct? A solution that signals the event more than is exactly needed is ok but not one that does so for every item.
This falls into the sub-category of "stop messing about and go back to work" known as "premature optimisation". :-)
If the "expensive" event operations are taking up a significant portion of time, your design is wrong, and rather than use a producer/consumer you should use a critical section/mutex and just do the work from the calling thread.
I suggest you profile your application if you are really concerned.
Updated:
Correct answer:
Producer
ProducerAddToQueue(pQueue,pItem){
EnterCriticalSection(pQueue->pCritSec)
if(IsQueueEmpty(pQueue)){
SignalEvent(pQueue->hEvent)
}
AddToQueue(pQueue, pItem)
LeaveCriticalSection(pQueue->pCritSec)
}
Consumer
nCheckQuitInterval = 100; // Every 100 ms consumer checks if it should quit.
ConsumerRun(pQueue)
{
while(!ShouldQuit())
{
Item* pCurrentItem = NULL;
EnterCriticalSection(pQueue-pCritSec);
if(IsQueueEmpty(pQueue))
{
ResetEvent(pQueue->hEvent)
}
else
{
pCurrentItem = RemoveFromQueue(pQueue);
}
LeaveCriticalSection(pQueue->pCritSec);
if(pCurrentItem){
ProcessItem(pCurrentItem);
pCurrentItem = NULL;
}
else
{
// Wait for items to be added.
WaitForSingleObject(pQueue->hEvent, nCheckQuitInterval);
}
}
}
Notes:
The event is a manual-reset event.
The operations protected by the critical section are quick. The event is only set or reset when the queue transitions to/from empty state. It has to be set/reset within the critical section to avoid a race condition.
This means the critical section is only held for a short time. so contention will be rare.
Critical sections don't block unless they are contended. So context switches will be rare.
Assumptions:
This is a real problem not homework.
Producers and consumers spend most of their time doing other stuff, i.e. getting the items ready for the queue, processing them after removing them from the queue.
If they are spending most of the time doing the actual queue operations, you shouldn't be using a queue. I hope that is obvious.
Went thru a bunch of cases, can't see an issue. But it's kinda complicated. I thought maybe you would have an issue with queue_not_empty / add_to_queue racing. But looks like the post-dominating CAS in both paths covers this case.
CAS is expensive (not as expensive as signal). If you expect skipping the signal to be common, I would code the CAS as follows:
bool cas(variable, old_val, new_val) {
if (variable != old_val) return false
asm cmpxchg
}
Lock-free structures like this is the stuff that Jinx (the product I work on) is very good at testing. So you might want to use an eval license to test the lock-free queue and signal optimization logic.
Edit: maybe you can simplify this logic.
running = false
// add item to queue – producer thread(s)
add_to_queue()
if (cas(running, false, true)) {
signal_event()
}
// Process queue, single consumer thread
reset_event()
while(1)
{
wait_for_auto_reset_event() // Preferably IOCP
for(int i = 0; i &lt SpinCount; ++i)
process_queue()
cas(running, true, false) // this could just be a memory barriered store of false
if(queue_not_empty())
if(cas(running, false, true))
signal_event()
}
Now that the cas/signal are always next to each other they can be moved into a subroutine.
Why not just associate a bool with the event? Use cas to set it to true, and if the cas succeeds then signal the event because the event must have been clear. The waiter can then just clear the flag before it waits
bool flag=false;
// producer
add_to_queue();
if(cas(flag,false,true))
{
signal_event();
}
// consumer
while(true)
{
while(queue_not_empty())
{
process_queue();
}
cas(flag,true,false); // clear the flag
if(queue_is_empty())
wait_for_auto_reset_event();
}
This way, you only wait if there are no elements on the queue, and you only signal the event once for each batch of items.
I believe, you want to achieve something like in this question:
WinForms Multithreading: Execute a GUI update only if the previous one has finished. It is specific on C# and Winforms, but the structure may well apply for you.

Resources