Throttling Events and Locking Methods

前端 未结 5 2033
小鲜肉
小鲜肉 2021-02-04 18:15

Let\'s pretend I have something like this:


And something like this:

publ         


        
5条回答
  •  死守一世寂寞
    2021-02-04 18:35

    While I kind of agree with James World, I think you can Do Better, if we use just a bit of mutable state. What if DoWork looked like this:

    AsyncSubject doingWork;
    public IObservable DoWork()
    {
        if (doingWork != null) return doingWork;
    
        doingWork = Observable.Start(() => {
            // XXX: Do work
            Thread.Sleep(1000);
    
            // We only kick off this 1sec timeout *after* we finish doing work
            Observable.Timer(TimeSpan.FromSeconds(1.0), DispatcherScheduler.Instance)
                .Subscribe(_ => doingWork = null);
        });
    
        return doingWork;
    }
    

    Now, DoWork debounces itself Automagically™, and we can get rid of this await-in-Subscribe silliness; we set the throttle to 250ms to be Quick-But-Not-Too-Quick.

    This initially appears to violate requirement #5 above, but we've ensured that anyone calling DoWork too quickly just gets the previous run's results - the effect will be that DoWork will be called many times, but not necessarily do anything. This ensures though, that if we aren't doing work, we won't have a 1sec delay after the user stops typing, like Throttle(1.seconds) would

        Observable.FromEventPattern(this, "PropertyChanged")
            .Where(x => x.EventArgs.PropertyName.Equals("Text"))
            .Throttle(TimeSpan.FromMilliseconds(250), DispatcherScheduler.Instance)
            .SelectMany(_ => DoWork())
            .Catch(ex => {
                Console.WriteLine("Oh Crap, DoWork failed: {0}", ex);
                return Observable.Empty();
            })
            .Subscribe(_ => Console.WriteLine("Did work"));
    

提交回复
热议问题