title: Does Async.StartChild have a memory leak?
body: <p>When I run the following test (built with F#2.0) I get OutOfMemoryException. It takes about 5 min to reach exception on my system (i7-920 6gb ram if it was running as x86 process), but in any case we can see how memory is growing in task manager.</p>
  
  <pre><code>module start_child_test
      open System
      open System.Diagnostics
      open System.Threading
      open System.Threading.Tasks
  
      let cnt = ref 0
      let sw = Stopwatch.StartNew()
      Async.RunSynchronously(async{
          while true do
              let! x = Async.StartChild(async{
                  if (Interlocked.Increment(cnt) % 100000) = 0 then
                      if sw.ElapsedMilliseconds &gt; 0L then
                          printfn "ops per sec = %d" (100000L*1000L / sw.ElapsedMilliseconds)
                      else
                          printfn "ops per sec = INF"
                      sw.Restart()
                      GC.Collect()
              })
              do! x
      })
  
      printfn "done...."
  </code></pre>
  
  <p>I don't see nothing wrong with this code, and don't see any reasons for memory growing. I made alternate implementation to make sure my arguments are valid:</p>
  
  <pre><code>module start_child_fix
      open System
      open System.Collections
      open System.Collections.Generic
      open System.Threading
      open System.Threading.Tasks
  
  
      type IAsyncCallbacks&lt;'T&gt; = interface
          abstract member OnSuccess: result:'T -&gt; unit
          abstract member OnError: error:Exception -&gt; unit
          abstract member OnCancel: error:OperationCanceledException -&gt; unit
      end
  
      type internal AsyncResult&lt;'T&gt; = 
          | Succeeded of 'T
          | Failed of Exception
          | Canceled of OperationCanceledException
  
      type internal AsyncGate&lt;'T&gt; = 
          | Completed of AsyncResult&lt;'T&gt;
          | Subscribed of IAsyncCallbacks&lt;'T&gt;
          | Started
          | Notified
  
      type Async with
          static member StartChildEx (comp:Async&lt;'TRes&gt;) = async{
              let! ct = Async.CancellationToken
  
              let gate = ref AsyncGate.Started
              let CompleteWith(result:AsyncResult&lt;'T&gt;, callbacks:IAsyncCallbacks&lt;'T&gt;) =
                  if Interlocked.Exchange(gate, Notified) &lt;&gt; Notified then
                      match result with
                          | Succeeded v -&gt; callbacks.OnSuccess(v)
                          | Failed e -&gt; callbacks.OnError(e)
                          | Canceled e -&gt; callbacks.OnCancel(e)
  
              let ProcessResults (result:AsyncResult&lt;'TRes&gt;) =
                  let t = Interlocked.CompareExchange&lt;AsyncGate&lt;'TRes&gt;&gt;(gate, AsyncGate.Completed(result), AsyncGate.Started)
                  match t with
                  | Subscribed callbacks -&gt; 
                      CompleteWith(result, callbacks)
                  | _ -&gt; ()
              let Subscribe (success, error, cancel) = 
                  let callbacks = {
                      new IAsyncCallbacks&lt;'TRes&gt; with
                          member this.OnSuccess v = success v
                          member this.OnError e = error e
                          member this.OnCancel e = cancel e
                  }
                  let t = Interlocked.CompareExchange&lt;AsyncGate&lt;'TRes&gt;&gt;(gate, AsyncGate.Subscribed(callbacks), AsyncGate.Started)
                  match t with
                  | AsyncGate.Completed result -&gt; 
                      CompleteWith(result, callbacks)
                  | _ -&gt; ()
  
              Async.StartWithContinuations(
                  computation = comp,
                  continuation = (fun v -&gt; ProcessResults(AsyncResult.Succeeded(v))),
                  exceptionContinuation = (fun e -&gt; ProcessResults(AsyncResult.Failed(e))),
                  cancellationContinuation = (fun e -&gt; ProcessResults(AsyncResult.Canceled(e))),
                  cancellationToken = ct
              )
              return Async.FromContinuations( fun (success, error, cancel) -&gt;
                  Subscribe(success, error, cancel)
              )
          }
  </code></pre>
  
  <p>For this test it works well without any considerably memory consumption. Unfortunately I'm not much experienced in F# and have doubts if I miss some things. In case if it is bug how can I report it to F# team?</p>