Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I have been digging around in this and found that it is indeed relatively easy. <a href="http://www.albahari.com/threading/" rel="nofollow">http://www.albahari.com/threading/</a> has got some good information and I actually ended up buying the book which that website is essentially promoting.</p> <p>What I found out is that;</p> <ul> <li>Your application has a ThreadPool available to it by default</li> <li>You can limit the number of threads available in the ThreadPool</li> <li>When you use <code>QueueUserWorkItem</code> or <code>Task.Factory.StartNew</code> the job you start run on a Thread in the ThreadPool</li> <li>When you use one of the asynchronous IO calls in the framework (<code>Begin...</code> methods or <code>WebcClient.DownloadStringAsync</code> 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).</li> </ul> <p>So far, so good. The problem is that I can keep calling <code>Task.Factory.StartNew</code> as much as I like and the ThreadPool will simply queue up the work until there are free threads to service them. <strong>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)</strong>. 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.</p> <p>This is a very simple example of how this could be achieved. In essence, I am using an <code>AutoResetEvent</code> 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.</p> <pre><code>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( () =&gt; { jobStart.Set(); // Will happen when the threadpool allocates this job to a thread this.Download(job); }); } </code></pre> <p>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 <code>ThreadPool.GetAvailableThreads</code> to check if there are free threads before starting to listen to the queue but that feels rather more error prone.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload