title: Using Rx Repeat() and Replay() to cache and restart a DNS query
body: <p>I'm a Rx newbie, so I hope you can bear with me.  As an exercise for myself, and possibly a sample I can demonstrate for colleagues, I've done two wrapper classes for Dns.BeginGetHostEntry()/EndGetHostEntry(): DnsResolver and DnsResolverRx.</p>
  
  <p>The classes each have a single public static method:</p>
  
  <pre><code>void Resolve(string host, Action&lt;IPHostEntry&gt; getResult, Control context = null);
  </code></pre>
  
  <p>...and some additional requirements to make it interesting:
  1. if context is provided, getResult must be invoked on the associated thread
  2. previous results for the same host are cached for MaxResultAge seconds.</p>
  
  <p>The non-Rx version works fine, but is not really relevant to this question.
  The Rx version looks like this:</p>
  
  <pre><code>class DnsResolverRx
  {
    static Func&lt;string, IObservable&lt;IPHostEntry&gt;&gt; _resolver = Observable.FromAsyncPattern&lt;string, IPHostEntry&gt;(Dns.BeginGetHostEntry, Dns.EndGetHostEntry);
  
    public static void Resolve(string host, Action&lt;IPHostEntry&gt; setResult, Control context = null)
    {
      IObservable&lt;IPHostEntry&gt; result;
      result = _cache.GetOrCreateValue( // a trivial TryGetValue wrapper
        host,
        () =&gt; _resolver(host)
          .Do(e =&gt; Debug.WriteLine("resolved"))
          .Repeat()
          .Do(e =&gt; Debug.WriteLine("repeated"))
          .Replay(MaxResultAge)
          .RefCount()
      );
  
      result = result.Take(1); // each request needs only 1 result
  
      if (context != null)
        result = result.ObserveOn(context);
  
      result.Subscribe(
        entry =&gt; setResult(entry),
        ex =&gt; setResult(null)
      );
    }
  }
  
  static void Main(string[] args)
  {
    for (int i=0; i&lt;10; ++i)
    {
      int num = i;
      Debug.WriteLine("start" + num);
      DnsResolverRx.Resolve("chief", e =&gt; Debug.WriteLine("done"+num));
      Thread.Sleep(200);
    }
  
    Console.ReadLine();
  }
  </code></pre>
  
  <p>Replay() seems to work, so the first requests within MaxResultAge are all completed, reusing the same result.  However, the next request triggers Repeat(), and I end up with a seemingly endless loop:</p>
  
  <pre><code>start0
  start1
  start2
  start3
  start4
  start5
  resolved
  repeated
  done0
  done1
  done2
  done3
  done4
  done5
  start6
  resolved
  repeated
  resolved
  repeated
  ... and so on ad infinitum
  </code></pre>
  
  <p>Can anyone enlighten me on what's going on, and what I'm doing wrong?</p>