title: IAsyncResult.AsyncWaitHandle.WaitOne() completes ahead of callback
body: <p>Here is the code:</p>
  
  <pre><code>class LongOp
  {
      //The delegate
      Action longOpDelegate = LongOp.DoLongOp;
      //The result
      string longOpResult = null;
  
      //The Main Method
      public string CallLongOp()
      {
          //Call the asynchronous operation
          IAsyncResult result = longOpDelegate.BeginInvoke(Callback, null);
  
          //Wait for it to complete
          result.AsyncWaitHandle.WaitOne();
  
          //return result saved in Callback
          return longOpResult;
      }
  
      //The long operation
      static void DoLongOp()
      {
          Thread.Sleep(5000);
      }
  
      //The Callback
      void Callback(IAsyncResult result)
      {
          longOpResult = "Completed";
          this.longOpDelegate.EndInvoke(result);
      }
  }
  </code></pre>
  
  <p>Here is the test case:</p>
  
  <pre><code>[TestMethod]
  public void TestBeginInvoke()
  {
      var longOp = new LongOp();
      var result = longOp.CallLongOp();
  
      //This can fail
      Assert.IsNotNull(result);
  }
  </code></pre>
  
  <p>If this is run the test case can fail.  Why exactly?</p>
  
  <p>There is very little documentation on how delegate.BeginInvoke works. Does anyone have any insights they would like to share?</p>
  
  <p><strong>Update</strong>
  This is a subtle race-condition that is not well documented in MSDN or elsewhere. The problem, as explained in the accepted answer, is that when the operation completes the Wait Handle is signalled, and then the Callback is executed. The signal releases the waiting main thread and now the Callback execution enters the "race". <a href="http://msdn.microsoft.com/en-us/magazine/cc163467.aspx" rel="noreferrer">Jeffry Richter's suggested implementation</a> shows what's happening behind the scenes:  </p>
  
  <pre><code>  // If the event exists, set it   
    if (m_AsyncWaitHandle != null) m_AsyncWaitHandle.Set();
  
    // If a callback method was set, call it  
    if (m_AsyncCallback != null) m_AsyncCallback(this);
  </code></pre>
  
  <p>For a solution refer to Ben Voigt's answer. That implementation does not incur the additional overhead of a second wait handle.</p>