3

私はRxの初心者なので、我慢していただければ幸いです。自分自身の演習として、またおそらく同僚に示すサンプルとして、Dns.BeginGetHostEntry()/EndGetHostEntry() の 2 つのラッパー クラスである DnsResolver と DnsResolverRx を作成しました。

各クラスには、単一の public static メソッドがあります。

void Resolve(string host, Action<IPHostEntry> getResult, Control context = null);

...そして、興味深いものにするためのいくつかの追加要件: 1. コンテキストが提供される場合、関連付けられたスレッドで getResult を呼び出す必要があります 2. 同じホストの以前の結果は MaxResultAge 秒間キャッシュされます。

非 Rx バージョンは正常に動作しますが、この質問にはあまり関係ありません。Rx バージョンは次のようになります。

class DnsResolverRx
{
  static Func<string, IObservable<IPHostEntry>> _resolver = Observable.FromAsyncPattern<string, IPHostEntry>(Dns.BeginGetHostEntry, Dns.EndGetHostEntry);

  public static void Resolve(string host, Action<IPHostEntry> setResult, Control context = null)
  {
    IObservable<IPHostEntry> result;
    result = _cache.GetOrCreateValue( // a trivial TryGetValue wrapper
      host,
      () => _resolver(host)
        .Do(e => Debug.WriteLine("resolved"))
        .Repeat()
        .Do(e => 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 => setResult(entry),
      ex => setResult(null)
    );
  }
}

static void Main(string[] args)
{
  for (int i=0; i<10; ++i)
  {
    int num = i;
    Debug.WriteLine("start" + num);
    DnsResolverRx.Resolve("chief", e => Debug.WriteLine("done"+num));
    Thread.Sleep(200);
  }

  Console.ReadLine();
}

Replay() は機能しているように見えるため、MaxResultAge 内の最初のリクエストはすべて完了し、同じ結果が再利用されます。ただし、次のリクエストで Repeat() がトリガーされ、一見エンドレス ループになってしまいます。

start0
start1
start2
start3
start4
start5
resolved
repeated
done0
done1
done2
done3
done4
done5
start6
resolved
repeated
resolved
repeated
... and so on ad infinitum

何が起こっているのか、何が間違っているのかを教えてくれる人はいますか?

4

1 に答える 1

6

わかりました - FromAsyncPatterns は基本的に再起動できない 1 回限りのものであり、サブスクライブしたときではなく、参照されたときに開始されることに気付きました。

交換する

_resolver(host)

Observable.Defer(() => _resolver(host))

トリックを行うようです。

誰も異議を唱えない場合 (そして他の問題を発見しない場合)、この回答をすぐに受け入れます。

于 2012-04-27T21:14:37.957 に答える