私はRx初心者ですから、あなたが私に耐えられることを願っています。自分自身の練習として、そしておそらくは同僚のために示すことができるサンプルとして、Dns.BeginGetHostEntry()/ EndGetHostEntry()のDnsResolverとDnsResolverRxの2つのラッパークラスを実行しました。Rx Repeat()とReplay()を使用してDNSクエリをキャッシュして再起動する
クラスそれぞれが単一の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();
}
リプレイ()が動作しているようですので、MaxResultAge内の最初の要求は、すべて同じ結果を再利用し、完成されています。ただし、次の要求は)(リピートをトリガし、私は表面上は無限ループで終わる:
start0
start1
start2
start3
start4
start5
resolved
repeated
done0
done1
done2
done3
done4
done5
start6
resolved
repeated
resolved
repeated
... and so on ad infinitum
、誰もが何が起こっているかに私を啓発し、私が間違ってやっていることはできますか?
それに釘付け。 'Retry'や' Repeat'を使うときに 'Defer'をしたいことがよくあります。 –