Rx.Net:无限地观察异步事件

时间:2017-03-19 11:05:41

标签: c# asynchronous rx.net

我有一个帮助类,可以将文本消息保存到本地文件系统。此方法返回Task对象,并且根据定义是异步的。

我希望能够观察何时调用此方法,因此我可以持续监视缓冲区的大小和长度,并根据该方法做出决定。

我正在尝试使用Reactive Extension for .NET实现这一点。但是,我无法想出一个允许我不断收听添加到缓冲区的消息的设计。以下是我目前的实施情况:

public IObservable<Unit> Receive(InternalMessage message)
        {
            var observable = FileBuffer.BufferMessage(message.MessageId.ToString(), message, DateTime.UtcNow).ToObservable(); //This returns a Task, which I convert into an Observable
            return observable;
        }

以下是我订阅observable的方式:

IObservable<Unit> receiverObservable = batchHandler.Receive(message);
            receiverObservable.Subscribe(
                x => Console.WriteLine("On next"),
                ex => //TODO,
                () => // Completed);

我希望每次调用方法Receive时都会调用订阅者。但是,AFAIK,一旦调用此方法,observable就会完成并且序列终止,因此将不会收听对Receive的未来调用。

有人可以推荐一种方法来使用Rx.Net库来实现我正在寻找的这种可观察模式,也就是说,如何保持序列打开并将其与异步方法的结果一起提供?

1 个答案:

答案 0 :(得分:1)

Receive正如您已对其进行编码,返回IObservable<Unit>,表示单个任务的完成情况。您希望订阅返回IObservable<IObservable<Unit>>表示任务完成流的内容。

有很多方法可以做到这一点,其中最好的方法可能取决于您的课程设置方式以及您如何调用课程。

这是最懒的一个:

您声明了一个代表您的通话流的类级变量subject

Subject<IObservable<Unit>> subject = new Subject<IObservable<Unit>>();
subject.Merge().Subscribe(
    x => Console.WriteLine("On next"),
    ex => { },  //TODO
    () => { }   // Completed
);

然后,当您有新的通话时,只需将其添加到主题中即可。

IObservable<Unit> receiverObservable = batchHandler.Receive(message);
subject.OnNext(receiverObservable);

这真的很懒的原因是Rx的核心是功能性的,它往往会忽视可变状态变量。 Subjects基本上是可变状态。

更好的方法是弄清楚你何时/为什么要调用Receive,并将其作为一个可观察的结构。一旦完成,你可以解决这个问题:

IObservable<Unit> sourceReasonsToCallReceive; // Most likely sourced from event

sourceReasonsToCallReceive.SelectMany(_ => batchHandler.Receive(message))
    .SubScribe(
    x => Console.WriteLine("On next"),
    ex => { },  //TODO
    () => { }   // Completed
);

希望有所帮助。