RX IObserver订阅时间

时间:2015-05-20 14:40:22

标签: c# .net system.reactive

我是.net中的Rx的新手,但已经开始使用它并成功完成了一些网络通信

非常简化示例:

    IObservable<Result> SendRequest(Request request)
    {
        return Observable.Create<Result>(observer =>
        {
            NetworkComms.SendReqeust(request,
                result =>
                {
                    observer.OnNext(result);
                    observer.OnCompleted();
                });
            return Disposable.Empty;
        }).SubscribeOn(_commsScheduler);
    }

我遇到的问题是,在调用者订阅返回的IObservable之前,实际上并不发送命令(NetworkComms.SendRequest)。在某些情况下,请求是fire-and-forget命令,结果毫无意义,因此调用者实际订阅返回的IObservable没什么意义。

我需要的功能是:

  1. 即使调用者从未订阅IObservable
  2. ,也会立即发送命令
  3. 如果客户订阅,即使订阅迟到,他们也会得到结果
  4. 该命令只发送一次,但所有订阅都应该得到相同的结果。
  5. 我尝试使用.Replay()。RefCount()并在返回IObservable之前在内部执行Subscribe()。这几乎可以工作,但是如果客户端在之后订阅收到的结果(因此在完成后自动处理序列之后),它会再次调用订阅代码,发送命令第二次。

    是否有一个简单的Rx扩展可以为我处理这种情况,还是我需要自己动手?

1 个答案:

答案 0 :(得分:4)

看起来您想要使用AsyncSubject<T>

IObservable<Result> SendRequest(Request request)
{
    var subject = new AsyncSubject<Result>();
    NetworkComms.SendReqeust(request, result =>
    {
        subject.OnNext(result);
        subject.OnCompleted();
    });
    return subject.AsObservable();
}

我应该补充一点,你想要的界面有点奇怪。如果语义是&#34;当我调用这个方法时,会发出一个请求,任何想要的人都可以在以后获得响应,&#34;然后考虑使用Task<Result>代替IObservable<Result>

Task<Result> SendRequestAsync(Request request)
{
    var tcs = new TaskCompletionSource<Result>();
    NetworkComms.SendReqeust(request, result => tcs.SetResult(result));
    return tcs.Task;
}

此外,请考虑将此Task<Result> SendRequestAsync(Request request)方法直接放在NetworkComms类上。