Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8030051
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 5, 20262026-06-05T00:38:25+00:00 2026-06-05T00:38:25+00:00

EDIT I realised my question was not stated clearly enough and have edited it

  • 0

EDIT I realised my question was not stated clearly enough and have edited it heavily.
This is a bit of an open ended question so apologies in advance.

In a nutshell, I want to implement IIS-style asynchronous request processing in an Azure worker role.

It may be very simple or it may be insanely hard – I am looking for pointers to where to research.

While my implementation will use Azure Workers and Service Bus Queues, the general principle is applicable to any scenario where a worker process is listening for incoming requests and then servicing them.

What IIS does

In IIS there is a fixed-size threadpool. If you deal with all request synchronously then the maximum number of requests you can deal with in parallel == maxthreads. However, if you have to do slow external I/O to serve requests then this is highly inefficient because you can end up with the server being idle, yet have all threads tied up waiting for external I/O to complete.

From MSDN:

On the Web server, the .NET Framework maintains a pool of threads that are used to service ASP.NET requests. When a request arrives, a thread from the pool is dispatched to process that request. If the request is processed synchronously, the thread that processes the request is blocked while the request is being processed, and that thread cannot service another request.

This might not be a problem, because the thread pool can be made large enough to accommodate many blocked threads. However, the number of threads in the thread pool is limited. In large applications that process multiple simultaneous long-running requests, all available threads might be blocked. This condition is known as thread starvation. When this condition is reached, the Web server queues requests. If the request queue becomes full, the Web server rejects requests with an HTTP 503 status (Server Too Busy).

In order to overcome this issue, IIS has some clever logic that allows you to deal with requests asynchronously:

When an asynchronous action is invoked, the following steps occur:

  1. The Web server gets a thread from the thread pool (the worker thread) and schedules it to handle an incoming request. This worker thread initiates an asynchronous operation.

  2. The worker thread is returned to the thread pool to service another Web request.

  3. When the asynchronous operation is complete, it notifies ASP.NET.

  4. The Web server gets a worker thread from the thread pool (which might be a different thread from the thread that started the asynchronous operation) to process the remainder of the request, including rendering the response.

The important point here is when the asynchronous request returns, the return action is scheduled to run on one of the same pool of threads that serves the initial incoming requests. This means that the system is limiting how much work it is doing concurrently and this is what I would like to replicate.

What I want to do

I want to create a Worker role which will listen for incoming work requests on Azure Service Bus Queues and also potentially on TCP sockets. Like IIS I want to have a maxium threadpool size and I want to limit how much actual work the worker is doing in parallel; If the worker is busy serving existing requests – whether new incoming ones or the callbacks from previous async calls – I don’t want to pick up any new incoming requests until some threads have been freed up.

It is not a problem to limit how many jobs I start concurrently – that is easy to control; It is limiting how many I am actually working on concurrently.

Let’s assume a threadpool of 100 threads.

  • I get 100 requests to send an email come in and each email takes 5 seconds to send to the SMTP server. If I limit my server to only process 100 requests at the same time then my server will be unable to do anything else for 5 seconds, while the CPU is completely idle. So, I don’t really mind starting to send 1,000 or 10,000 emails at the same time, because 99% of the "request process time" will be spent waiting for external I/O and my server will still be very quiet.
    So, that particular scenario I could deal with by just keeping on accepting incoming requests with no limit (or only limit the start of the request until I fire off the async call; as soon as the BeginSend is called, I’ll return and start serving another request).

  • Now, imagine instead that I have a type of request that goes to the database to read some data, does some heavy calculation on it and then writes that back to the database. There are two database requests there that should be made asynchronous but 90% of the request processing time will be spent on my worker. So, if I follow the same logic as above and keep start async calls and just letting the return do whatever it needs to get a thread to continue on then I will end up with a server that is very overloaded.

Somehow, what IIS does is make sure that when an async call returns it uses the same fixed-size thread pool. This means that if I fire off a lot of async calls and they then return and start using my threads, IIS will not accept new requests until those returns have finished. And that is perfect because it ensures a sensible load on the server, especially when I have multiple load-balanced servers and a queue system that the servers pick work from.

I have this sneaky suspicion that this might be very simple to do, there is just something basic I am missing. Or maybe it is insanely hard.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-05T00:38:28+00:00Added an answer on June 5, 2026 at 12:38 am

    I have been digging around in this and found that it is indeed relatively easy.
    http://www.albahari.com/threading/ has got some good information and I actually ended up buying the book which that website is essentially promoting.

    What I found out is that;

    • Your application has a ThreadPool available to it by default
    • You can limit the number of threads available in the ThreadPool
    • When you use QueueUserWorkItem or Task.Factory.StartNew the job you start run on a Thread in the ThreadPool
    • When you use one of the asynchronous IO calls in the framework (Begin... methods or WebcClient.DownloadStringAsync etc) the the callbacks will also run on a Thread from the ThreadPool (what happens with the IO request itself is outside the scope of this discussion).

    So far, so good. The problem is that I can keep calling Task.Factory.StartNew as much as I like and the ThreadPool will simply queue up the work until there are free threads to service them. So, in the case of an Azure Worker, I could easily empty the Queue even though my worker is busy servicing existing requests (and callbacks from existing requests). That is the core of my problem. What I want is to not take anything out of the queue until I actually have some free threads to service the request.

    This is a very simple example of how this could be achieved. In essence, I am using an AutoResetEvent to make sure that I don’t start another task from the queue until the previous task has actually started. Granted, I do actually take stuff out of the queue before there is a free thread, but on balance this should avoid crazy overloads of the worker and allow me to spin up more workers to share the load.

    ThreadPool.SetMaxThreads(5, 1000); // Limit to 5 concurrent threads
    ThreadPool.SetMinThreads(5, 10); // Ensure we spin up all threads
    
    var jobStart = new AutoResetEvent(true);
    
    // The "listen" loop
    while (true) 
    {   
        var job = this.jobQueue.Dequeue();
        jobStart.WaitOne(); // Wait until the previous job has actually been started
        Task.Factory.StartNew(
            () =>
                {
                    jobStart.Set(); // Will happen when the threadpool allocates this job to a thread
                    this.Download(job);
                });
    
    }
    

    This can – and probably should – be made a lot more sophisticated, including having timeouts, putting the work item back in the queue if a thread can’t be allocated within a reasonable time and so on.
    An alternative would be to use ThreadPool.GetAvailableThreads to check if there are free threads before starting to listen to the queue but that feels rather more error prone.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Apologies for reposting but I had to edit this question when I got to
a simple question but Ive realised im not sure of the answer for this
I have a quick question regarding memory management that I am not quite sure
EDIT: I just realized that this question may be better suited to ServerFault. Instead
Maybe this is a stupid question but it's bugging me. I have a bi-directional
I've searched around for answers to this question, but not found anything quite on
Edit: The bug which prompted this question has now been fixed . In the
Edit: For simplicity, and in order to try and make this question and the
I'm not even sure if this is possible, so apologies if it's a stupid
I think I may have overlooked something here, but I'm not sure why this

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.