Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I see a couple of problems with the code.</p> <ul> <li>The check of <code>StopRequested</code> is not thread-safe.</li> <li>The check of <code>ExecutingTaskCount</code> is not thread-safe.</li> <li>Since <code>_finishedTaskAutoResetEvent</code> is an <code>AutoResetEvent</code> signals can get lost because that <code>WaitHandle</code> does not maintain a count. Maybe that is what you want, but it could result in some strange spinning of the nested <code>while</code> loops.</li> </ul> <p>Here is how I would refactor your code. It uses the <code>CountdownEvent</code> class which is available in .NET 4.0.</p> <pre><code>public class TaskScheduler : ServiceBase { private m_Stop as ManualResetEvent = new ManualResetEvent(false); protected override void OnStart(string[] args) { var thread = new Thread(DoSpawnTaskExecutionThreads); thread.Name = "Spawning Thread"; thread.IsBackground = false; thread.Start(); } protected override OnStop() { m_Stop.Set(); } public DoSpawnTaskExecutionThreads() { // The semaphore will control how many concurrent tasks can run. var pool = new Semaphore(MaxPooledThreads, MaxPooledThreads); // The countdown event will be used to wait for any pending tasks. // Initialize the count to 1 so that we treat this thread as if it // were a work item. This is necessary to avoid a subtle race // with a real work item that completes quickly. var tasks = new CountdownEvent(1); // This array will be used to control the spinning of the loop. var all = new WaitHandle[] { pool, m_Stop }; while (WaitHandle.WaitAny(all) == 0) { // Indicate that there is another task. tasks.AddCount(); // Queue the task. Thread.QueueUserWorkItem( (state) =&gt; { try { var task = (Task)state; task.Execute(); } finally { pool.Release(); // Allow another task to be queued. tasks.Signal(); // Indicate that this task is complete. } }, new Task()); } // Indicate that the main thread is complete. tasks.Signal(); // Wait for all pending tasks. tasks.Wait(); } } </code></pre>
 

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