C# 处理订阅时访问当前窗口

C# 处理订阅时访问当前窗口,c#,system.reactive,C#,System.reactive,我有以下代码: var observable = ... subscribe to event here ... var windows = observable.Window(TimeSpan.FromSeconds(240)); aggregatedWindows = windows.SelectMany( window => window.Aggregate(new Context(), AggregateContext)); subscription = aggreg

我有以下代码:

var observable = ... subscribe to event here ...

var windows = observable.Window(TimeSpan.FromSeconds(240));

aggregatedWindows = windows.SelectMany(
    window => window.Aggregate(new Context(), AggregateContext));

subscription = aggregatedWindows.Subscribe(OnWindow);

... later

subscription.Dispose();
想象一下,当我在处理窗口时,有人请求我的应用程序关闭。我将处理此订阅,这将停止正在处理的事件,但是我也将丢失最后一个信息窗口

我不确定处理这件事的最好方法是

我可以存储本地状态和最后一次看到的窗口,因为它是通过聚合函数传递的,但这似乎是错误的


任何帮助都将不胜感激

您可以对窗口进行操作,而不是保留聚合订阅,这是您主要希望在最后一个窗口到达时保持连接的窗口,并使用超时来断开连接,以防分区时间过长

这里使用了一个单独的类,因为使用Create会使其自动分离-这会在发出dispose调用后立即断开观察者的连接。因此,从根本上讲,Dispose的含义在这里发生了变化

    public static IObservable<T> DeferDisconnection<T>(this IObservable<T> observable, TimeSpan timeout)
    {
        return new ClosingObservable<T>(observable, timeout);
    }


    public class ClosingObservable<T> : IObservable<T>
    {

        private readonly IConnectableObservable<T> Source;
        private readonly IDisposable Subscription;
        private readonly TimeSpan Timeout;

        public ClosingObservable(IObservable<T> observable, TimeSpan timeout)
        {
            Timeout = timeout;
            Source = observable.Publish();
            Subscription = Source.Connect();
        }

        public IDisposable Subscribe(IObserver<T> observer)
        {
            Source.Subscribe(observer);

            return Disposable.Create(() => Source.Select(_ => new Unit())
                                                 .Amb(Observable.Timer(Timeout).Select(_ => new Unit()))
                                                 .Subscribe(_ => Subscription.Dispose())
                                                 );
        }
    }

最后显示的部分窗口证实了这一点

class Program
{
    public class Context
    {
        public int count;
    }

    static Context AggregateContext(Context c, long i)
    {
        c.count++;
        return c;
    }

    static void OnWindow(Context c) { Console.WriteLine(c.count); }

    static void Main(string[] args)
    {
        var canceled = new Subject<bool>();

        var observable = Observable.Interval(TimeSpan.FromSeconds(.1)).TakeUntil(canceled);

        var windows = observable.Window(TimeSpan.FromSeconds(3));

        var aggregatedWindows = windows.SelectMany(
            window => window.Aggregate(new Context(), AggregateContext));

        var subscription = aggregatedWindows.Subscribe(OnWindow);

        Thread.Sleep(TimeSpan.FromSeconds(10));

        canceled.OnNext(true);
        subscription.Dispose();

        Console.WriteLine( @"Output should have been something like 30,30,30,30,10" );
        Console.ReadLine();
    }
} 

我不明白这是如何解决问题的。看起来在处理之前,应用程序将等待一段时间,但如果窗口较大,则会导致应用程序等待很长时间才能关闭。这是正确的吗?@jonnii这就是为什么会有一个timeout参数-它会在下一个值到达时断开连接,或者如果它花费的时间太长,这就是timeout参数。
class Program
{
    public class Context
    {
        public int count;
    }

    static Context AggregateContext(Context c, long i)
    {
        c.count++;
        return c;
    }

    static void OnWindow(Context c) { Console.WriteLine(c.count); }

    static void Main(string[] args)
    {
        var canceled = new Subject<bool>();

        var observable = Observable.Interval(TimeSpan.FromSeconds(.1)).TakeUntil(canceled);

        var windows = observable.Window(TimeSpan.FromSeconds(3));

        var aggregatedWindows = windows.SelectMany(
            window => window.Aggregate(new Context(), AggregateContext));

        var subscription = aggregatedWindows.Subscribe(OnWindow);

        Thread.Sleep(TimeSpan.FromSeconds(10));

        canceled.OnNext(true);
        subscription.Dispose();

        Console.WriteLine( @"Output should have been something like 30,30,30,30,10" );
        Console.ReadLine();
    }
}