title: Using BeginInvoke/EndInvoke in a multithreaded fashion. How do AsyncCallback, AsyncWaitHandle and IsCompleted interact?
body: <p>Andreas Huber's answer to <a href="https://stackoverflow.com/questions/405600/detecting-that-a-threadpool-workitem-has-completed-waiting-for-completion">this question</a> gave me an idea to implement <code>Concurrent&lt;T&gt;</code> with async delegates instead of the ThreadPool. However, I am finding it harder to understand what's going on when an <code>AsyncCallback</code> is passed to <code>BeginInvoke</code>, especially when several threads have access to <code>IAsyncResult</code>. Unfortunately, this case doesn't seem to be covered at MSDN or anywhere I could find. Moreover, all articles I could find were either written before closures and generics were available or just seem that way. There are several questions (and the answers which I hope are true, but I am ready to be disappointed):</p>
  
  <p>1) Would using a closure as an AsyncCallback make any difference?<br>
  (Hopefully not)<br>
  2) If a thread waits on the <code>AsyncWaitHandle</code>, will it be signaled<br>
  a) before the callback starts or 
  b) after it finishes?<br>
  (Hopefully b)<br>
  3) While the callback is running, what will <code>IsCompleted</code> return? Possibilities I can see:<br>
  a) <code>true</code>;
  b) <code>false</code>;
  c) <code>false</code> before the callback calls EndInvoke, <code>true</code> after.<br>
  (Hopefully b or c)<br>
  4) Will <code>DisposedObjectException</code> be thrown if some thread waits on the <code>AsyncWaitHandle</code> after <code>EndInvoke</code> is called?<br>
  (Hopefully not, but I expect yes).</p>
  
  <p>Provided the answers are as I hope, this seems like it should work:</p>
  
  <pre><code>public class Concurrent&lt;T&gt; { 
      private IAsyncResult _asyncResult;
      private T _result;
  
      public Concurrent(Func&lt;T&gt; f) { // Assume f doesn't throw exceptions
          _asyncResult = f.BeginInvoke(
                             asyncResult =&gt; {
                                 // Assume assignment of T is atomic
                                 _result = f.EndInvoke(asyncResult); 
                             }, null);
      }
  
      public T Result {
          get {
              if (!_asyncResult.IsCompleted)
                  // Is there a race condition here?
                  _asyncResult.AsyncWaitHandle.WaitOne();
              return _result;  // Assume reading of T is atomic
          }
      ...
  </code></pre>
  
  <p>If the answers to the questions 1-3 are the ones I hope for, there should be no raace condition here, as far as I can see.</p>