Last post May 09, 2020 07:59 PM by email@example.com
May 08, 2020 07:41 PMfirstname.lastname@example.org|LINK
I've read a number of posts about RegisterWaitForSingleObject and the main conclusion to all this is it's very easy to use this wrong. Hence my question.
The below is greatly simplified to keep the focus on RegisterWaitForSingleObject.
I have a cluster of several REST web apps (ASP.NET Web API2 if that matters) that each will get requests for jobs that take between 5 seconds and 15 minutes. So each request is saved in a SQL database.
Then when one of the web apps has an available background thread from the ThreadPool, it gets the next job from the SQL database, and processes it. When complete, it writes the result to the database.
When any of the web apps is asked for the status of a job, it reads from the database and returns the result if the request is completed.
My question is how do I use RegisterWaitForSingleObject to have it call me when a background thread is free. In a way that will create up to the max in the ThreadPool immediately, then not trigger until a thread is available.
This way I have all web apps running at full speed, but no requests pending waiting for an available thread when another web app has available background threads.
May 09, 2020 04:39 PM|bruce (sqlwork.com)|LINK
RegisterWaitForSingleObject is used implement a mutex or semaphore. I'm not sure its use case in your case.
as the queue is a sql database, each thread need to query the database to get then next job. this is a simple loop
job = getjob
just start as many thread as you want. your issue will be what to do when the queue is empty. does the thread sleep and poll. I would probably use processing thread that used an internal queue feed by one job queue builder. I’d use a Blocking Collection
for the job queue and a interlock (hardware rather than spin lock) to count working threads
and queue builder looks like:
var Jobs = new ConcurrentQueue<Job>();
var maxThreads = startBackGroundThreads(Jobs, ref processCount);
if (processCount < maxThreads)
var job = await GetSqlJob();
if (job != null)
the job processor
private ProcessJob(ref long proessCount)
var job = Jobs.Take()
InterLocked.Add(ref processCount, 1);
InterLocked.Add(ref processCount, -1);
you should support cancellation tokens and error handling
May 09, 2020 07:59 PMemail@example.com|LINK
Yes, that looks better.
thanks - dave