title: C# SpinWait for long-term waiting
body: <p>This code consumes near zero CPU (i5 family)</p>
  
  <pre><code>    public void SpinWait() {
  
          for (int i = 0; i &lt; 10000; i++)
          {
              Task.Factory.StartNew(() =&gt;
              {
                  var sw = new SpinWait();
                  while (true)
                  {
                      sw.SpinOnce();
                  }
              });
          }
      }
  </code></pre>
  
  <p>In my code performance difference compared to SemaphoreSlim is 3x times or more for the case when spinning is really justified (5 Mops). However, I am concerned about using it for long-term wait. The standard advice is to implement two-phase wait operation. I could check <code>NextSpinWillYield</code> property and introduce a counter+reset to increase the default spinning iterations without yielding, and than back off to a semaphore.</p>
  
  <p>But what are downsides of using just <code>SpinWait.SpinOnce</code> for long-term waiting? I have looked through its <a href="http://referencesource.microsoft.com/#mscorlib/system/threading/SpinWait.cs,39bd72970cc926fe" rel="noreferrer">implementation</a> and it properly yields when needed. It uses <code>Thread.SpinWait</code> which on modern CPUs uses PAUSE instruction and is quite efficient according to <a href="https://software.intel.com/en-us/articles/long-duration-spin-wait-loops-on-hyper-threading-technology-enabled-intel-processors" rel="noreferrer">Intel</a>.</p>
  
  <p>One issue that I have found while monitoring Task Manager is that number of threads if gradually increasing due to the default ThreadPool algorithm (it adds a thread every second when all tasks are busy). This could be solved by using <code>ThreadPool.SetMaxThreads</code>, and then the number of threads is fixed and CPU usage is still near zero.</p>
  
  <p>If the number of long-waiting tasks is bounded, what are other pitfalls of using <code>SpinWait.SpinOnce</code> for long-term waiting. Does it depend on CPU family, OS, .NET version?</p>
  
  <p>(Just to clarify: I will still implement two-phase waiting, I am just curios why not using SpinOnce all the time?)</p>