C# - Worker thread with slots, items being dynamically added - windows

I have window service that polls a web service for new items every 30 seconds. If it finds any new items, it checks to see if they need to be "processed" and then puts them in a list to process. I spawn off different threads to process 5 at a time, and when one finishes, another one will fill the empty slot. Once everything has finished, the program sleeps for 30 seconds and then polls again.
My issue is, while the items are being processed(which could take up to 15 minutes), new items are being created which also may need to be processed. My problem is the main thread gets held up waiting for every last thread to finish before it sleeps and starts the process all over.
What I'm looking to do is have the main thread continue to poll the web service every 30 seconds, however instead of getting held up, add any new items it finds to a list, which would be processed in a separate worker thread. In that worker thread, it would still have say only 5 slots available, but they would essentially always all be filled, assuming the main thread continues to find new items to process.
I hope that makes sense. Thanks!
EDIT: updated code sample
I put together this as a worker thread that operates on a ConcurrentQueue. Any way to improve this?
private void ThreadWorker() {
DateTime dtStart = DateTime.Now;
int iNumOfConcurrentSlots = 6
Thread[] threads = new Thread[iNumOfConcurrentSlots];
while (true) {
for (int i = 0; i < m_iNumOfConcurrentSlots; i++) {
if (m_tAssetQueue.TryDequeue(out Asset aa)) {
threads[i] = new Thread(() => ProcessAsset(aa));
threads[i].Start();
Thread.Sleep(500);
}
}
}
}
EDIT: Ahh yeah that won't work above. I need a way of being able to not hard code the number of ConcurrentSlots, but have each thread basically waiting and looking for something in the Queue and if it finds it, process it. But then I also need a way of signalling that the ProcessAsset() function has completed to release the thread and allow another thread to be created....

One simple way to do it is to have 5 threads reading from a concurrent queue. The main thread queues items and the worker threads do blocking reads from the queue.
Note: The workers are in an infinite loop. They call TryDequeue, process the item if they got one or sleep one second if they fail to get something. They can also check for an exit flag.
To have your service property behaved, you might have an independent polling thread that queues the items. The main thread is kept to respond to start, stop, pause requests.
Pseudo code for worker thread:
While true
If TryDequeue then
process data
If exit flag is true, break
While pause flag, sleep
Sleep
Pseudo code for polling thread:
While true
Poll web service
Queue items in concurrent queue
If exit flag true, break
While pause flag, sleep
Sleep
Pseudo code for main thread:
Start polling thread
Start n worker threads with above code
Handle stop:
set exit flag to true
Handle pause
set pause flag to true

Related

ruby multithreading - stop and resume specific thread

I want to be able to stop and run specific thread in ruby in the following context:
thread_hash = Hash.new()
loop do
Thread.start(call.function) do |execute|
operation = execute.extract(some_value_from_incoming_message)
if thread_hash.has_key? operation
thread_hash[operation].run
elsif !thread_hash.has_key?
thread_hash[operation] = Thread.current
do_something_else_1
Thread.stop
do_something_else_2
Thread.stop
do_something_else_3
thread_hash.delete(operation)
else
exit
end
end
end
In human language script above acts as a server which receives a message, extracts some parameter from the incoming message. If that parameter is already in the thread_hash, suspended thread should be resumed.
If the parameter is not present in the thread_hash, parameter along with thread id is stored in the thread_hash, some function is executed and current thread is suspended until resumed in the new loop and again until do_something_else_3 function is executed and operation serviced in the current thread is removed from hash.
Can thread be resumed in Ruby based on thread id or should new thread be given name during start like
thr = Thread.start
and can be resumed only by this name like:
thr.run
Is the solution described above realistic? Could it cause some sort of leak/deadlock due to old thread resumption in the new thread or redundant threads are automatically taken care of by Ruby?
It sounds to me like you're trying to do everything in every thread: read input, run existing threads, store new threads, delete old threads. Why not break up the problem?
hash = {}
loop do
operation = get_value_from message
if hash[operation] and hash[operation].alive?
hash[operation].wakeup
else
hash[operation] = Thread.new do
do_something1
Thread.stop
do_something2
Thread.stop
do_something3
end
end
end
Instead of wrapping the whole contents of the loop in a thread, only thread the message processing code. That lets it run in the background while the loop goes back to waiting for a message. This solves any sort of race/deadlock problem since all of the thread management occurs in the main thread.

Highest thread priority and infinite loop without sleep in Windows

I've been reading about thread priorities on MSDN and I created a test program that has two threads. One of the threads prints out some text and then sleeps while the other thread runs an infinite loop where it increments some number and does so without sleep. I set the latter thread to have a higher priority than the former and according to what I'm reading this should means that the former thread doesn't get any CPU-time.
But it does..
Why is this?
The first thread is created using:
HANDLE threadL = CreateThread(NULL, 0, threadLow, NULL, 0, &threadLiD);
and the other thread is just the main thread where I've put this command:
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);

Spring #Async cancel and start?

I have a spring MVC app where a user can kick off a Report generation via button click. This process could take few minutes ~ 10-20 mins.
I use springs #Async annotation around the service call so that report generation happens asynchronously. While I pop a message to user indicating job is currently running.
Now What I want to do is, if another user (Admin) can kick off Report generation via the button which should cancel/stop currently running #Async task and restart the new task.
To do this, I call the
.. ..
future = getCurrentTask(id); // returns the current task for given report id
if (!future.isDone())
future.cancel(true);
service.generateReport(id);
How can make it so that "service.generateReport" waits while the future cancel task kills all the running threads?
According to the documentation, after i call future.cancel(true), isDone will return true as well as isCancelled will return true. So there is no way of knowing the job is actually cancelled.
I can only start new report generation when old one is cancelled or completed so that it would not dirty data.
From documentation about cancel() method,
Subsequent calls to isCancelled() will always return true if this method returned true
Try this.
future = getCurrentTask(id); // returns the current task for given report id
if (!future.isDone()){
boolean terminatedImmediately=future.cancel(true);
if(terminatedImmediately)
service.generateReport(id);
else
//Inform user existing job couldn't be stopped.And to try again later
}
Assuming the code above runs in thread A, and your recently cancelled report is running in thread B, then you need thread A to stop before service.generateReport(id) and wait until thread B is completes / cancelled.
One approach to achieve this is to use Semaphore. Assuming there can be only 1 report running concurrently, first create a semaphore object acccessible by all threads (normally on the report runner service class)
Semaphore semaphore = new Semaphore(1);
At any point on your code where you need to run the report, call the acquire() method. This method will block until a permit is available. Similarly when the report execution is finished / cancelled, make sure release() is called. Release method will put the permit back and wakes up other waiting thread.
semaphore.acquire();
// run report..
semaphore.release();

Make parent thread wait till child thread finishes in VC

According to MSDN:
The WaitForSingleObject function can wait for the following objects:
Change notification
Console input
Event
Memory resource notification
Mutex
Process
Semaphore
Thread
Waitable timer
Then we can use WaitForSingleObject to make the parent-thread wait for child ones.
int main()
{
HANDLE h_child_thread = CreateThread(0,0, child, 0,0,0); //create a thread in VC
WaitForSingleObject(h_child_thread, INFINITE); //So, parent-thread will wait
return 0;
}
Question
Is there any other way to make parent-thread wait for child ones in VC or Windows?
I don't quite understand the usage of WaitForSingleObject here, does it mean that the thread's handle will be available when the thread terminates?
You can establish communication between threads in multiple ways and the terminating thread may somehow signal its waiting thread. It could be as simple as writing some special value to a shared memory location that the waiting thread can check. But this won't guarantee that the terminating thread has terminated when the waiting thread sees the special value (ordering/race conditions) or that the terminating thread terminates shortly after that (it can just hang or block on something) and it won't guarantee that the special value gets ever set before the terminating thread actually terminates (the thread can crash). WaitForSingleObject (and its companion WaitForMultipleObjects) is a sure way to know of a thread termination when it occurs. Just use it.
The handle will still be available in the sense that its value won't be gone. But it is practically useless after the thread has terminated, except you need this handle to get the thread exit code. And you still need to close the handle in the end. That is unless you're OK with handle/memory leaks.
for the first queation - yes. The method commonly used here is "Join". the usage is language dependant.
In .NET C++ you can use the Thread's Join method. this is from the msdn:
Thread* newThread = new Thread(new ThreadStart(0, Test::Work));
newThread->Start();
if(newThread->Join(waitTime + waitTime))
{
Console::WriteLine(S"New thread terminated.");
}
else
{
Console::WriteLine(S"Join timed out.");
}
Secondly, the thread is terminated when when you are signaled with "WaitForSingleObject" but the handle is still valid (for a terminated thread). So you still need to explicitly close the handle with CloseHandle.

pthread-based event waking up only waiting threads

In my C++ program I have a class CEvent with trigger and wait member functions based on pthreads (running on Linux). Implementation is quite obvious (i.e. many examples online) if there is one waiting process. However now I need to satisfy the requirement that multiple threads are waiting on the event and should ALL wake up reliably when trigger() is called. As a second condition, only threads that were waiting when trigger() was called should wake up.
My current code:
void CEvent::trigger() {
pthread_mutex_lock(&mutex);
wakeUp = true;
pthread_cond_broadcast(&condition)
pthread_mutex_unlock(&mutex);
wakeUp = false;
}
void CEvent::wait() {
pthread_mutex_lock(&mutex);
while (!wakeUp)
pthread_cond_wait(&condition, &mutex)
pthread_mutex_unlock(&mutex);
}
This seems to almost work, insofar as that all threads waiting wake up before I set wakeUp back to false. However between the broadcast and the reset of wakeUp, other (or the same) threads calling wait() will also wake up right away which is not acceptable. Putting wakeUp = false before the mutext unlocking prevents the threads from waking up.
My questions:
* When does pthread_cond_broadcast return? I.e. is there a guarantee it will only return after all threads have woken up or could it return before?
* Are there any recommended solutions to this problem?
Please disregard my previous bogus answer. There is a race between the time that the trigger thread unlocks the mutex (and thus frees the waiting threads), and then sets the wakeUp value. This means that another (not waiting) thread can come in, grab the mutex, and see a true value in wakeUp and exit without waiting. Another bug is that a thread which was waiting will wake up after wakeUp is reset and immediately resume waiting.
One way to resolve this is to use count - each thread that is waiting will increment the count, then the trigger will wait until that many threads have woken before resuming. You would then have to ensure that non-waiting threads are not allowed to start waiting until this had happened.
// wake up "waiters" count of waiting threads
void CEvent::trigger()
{
pthread_mutex_lock(&mutex);
// wakey wakey
wakeUp = true;
pthread_cond_broadcast(&condition);
// wait for them to awake
while (waiters>0)
pthread_cond_wait(&condition, &mutex);
// stop waking threads up
wakeUp = false;
// let any "other" threads which were ready to start waiting, do so
pthread_cond_broadcast(&condition);
pthread_mutex_unlock(&mutex);
}
// wait for the condition to be notified for us
void CEvent::wait()
{
pthread_mutex_lock(&mutex);
// wait for us to be allowed to start waiting
// we have to wait until any currrently being woken threads have gone
while (wakeUp)
pthread_cond_wait(&condition, &mutex);
// our turn to start waiting
waiters ++;
// waiting
while (!wakeUp)
pthread_cond_wait(&condition, &mutex);
// finished waiting, we were triggered
waiters --;
// let the trigger thread know we're done
pthread_cond_broadcast(&condition);
pthread_mutex_unlock(&mutex);
}

Resources