为新订阅者发布事件的最后值

本文关键字:事件 最后 新订阅 布事件 | 更新日期: 2023-09-27 18:08:13

我有一个类Foo,其事件发布FooState enum。我想把这个事件变成一个可观察对象,为新的订阅者重放最后一个值。

即使没有订阅者,任何新的订阅者都应该获得最后一个值。

public enum FooState
{
    Stopped = 0,
    Starting = 1,
    Running = 2,        
}
public delegate void FooEventHandler(object sender, FooEventArgs e);
public class FooEventArgs : EventArgs
{
    public FooEventArgs(FooState fooState)
    {
        this.State = fooState;
    }
    public FooState State {get; private set;}
}
public class Foo
{
    public event FooEventHandler FooEvent;
    public void OnFooEvent(FooState state)
    {
        var fooEvent = FooEvent;
        if(fooEvent != null)
        {
            fooEvent(this, new FooEventArgs(state));
        }
    }
}

到目前为止,我的尝试围绕着使用Publish, RefCountReplay。但是,如果我在触发事件后订阅可观察对象,那么我尝试的所有组合都不起作用。

只要有至少一个订阅,Replay(1).RefCount()就可以工作,但我也需要为第一个晚订阅工作。

var foo = new Foo();
   var obs =  Observable.FromEventPattern<FooEventHandler, FooEventArgs>(
                                        h => foo.FooEvent += h,
                                        h => foo.FooEvent -= h)
                                    .DistinctUntilChanged()
                                    .Replay(1)
                                    .RefCount();
    // Works if this line is uncomented.
    //obs.Subscribe(x => Console.WriteLine("Early Subscriber = " + x.EventArgs.State));
    foo.OnFooEvent(FooState.Running);
    obs.Subscribe(x => Console.WriteLine("Late Subscriber = " + x.EventArgs.State));

有人知道如何用Rx做这个吗?

为新订阅者发布事件的最后值

RefCount只在第一次订阅后连接。如果你想细粒度地控制连接发生的时间,你应该使用Replay + Connect

var publishedSource = eventSource.DistinctUntilChanged().Replay(1);
var connection = publishedSource.Connect();
//Subscribe to publishedSource to receive events and dispose of 
connection when you are done.

从我的手机上发布的,所以提前为任何语法错误道歉。

Rx正在做正确的事情,将您的事件通知转换为您的流并重播它们,但您要问的是:"为什么当我订阅事件时,我没有得到初始状态"。

事件不是这样工作的。如果我对foo做a +=。FooEvent,我没有得到当前值的立即触发器。只有当它改变时我才会收到通知。正如您所注意到的,'Replay'将重播后续事件,但不提供订阅时的状态。

要解决您的问题,您需要确保在连接流以获得更改通知之前将当前值放入流中。查看Observable.StartWith().

。在. distinctuntilchanged()调用之前执行". startwith (foo.State)"(紧跟在. fromeventpattern之后)