代码之家  ›  专栏  ›  技术社区  ›  SuperJMN

如何根据一个可观测序列计算一个ETA?

  •  1
  • SuperJMN  · 技术社区  · 6 年前

    我有一个方法可以在给定的时间发送完成百分比的推送更新。

    public Task MyMethod(IObserver<double> progress)
    {
       ...
    }
    

    ISubject<double> progressObserver = new Subject<double>();
    await MyMethod(progressObserver);
    

    subject

    progressObserver.Subscribe(percent => Console.WriteLine(percent));
    

    Observables n

    2 回复  |  直到 6 年前
        1
  •  1
  •   Enigmativity    6 年前

    IObservable<Timestamped<double>> estimatedCompletion =
        progressObservable
            .Timestamp()
            .Buffer(2, 1)
            .Where(x => x.Count() == 2)
            .Scan((a, b) => a.Take(1).Concat(b).Take(1).Concat(b.Skip(1)).ToList())
            .Select(x => new
            {
                current = x[1].Value,
                delta = x[1].Timestamp.Subtract(x[0].Timestamp),
            })
            .Select(x => new
            {
                x.current,
                rate = x.current / x.delta.TotalSeconds,
            })
            .Select(x => new
            {
                x.current,
                estimated = DateTimeOffset.Now.AddSeconds((1.0 - x.current) / x.rate),
            })
            .Select(x => new Timestamped<double>(x.current, x.estimated));
    

    IObservable<Timestamped<double>> DateTimeOffset 1.0 100%

    .Buffer(2, 1).Where(x => x.Count() == 2) .Scan((a, b) => a.Take(1).Concat(b).Take(1).Concat(b.Skip(1)).ToList())

    您可以使用以下代码测试它:

    var rnd = new Random();
    var progressObservable = Observable.Generate(0, x => x <= 100, x => x + 1, x => x / 100.0, x => TimeSpan.FromSeconds(rnd.NextDouble()));
    
        2
  •  1
  •   Shlomo    6 年前

    它可能看起来像这样:

    var secondsRemaining = progressObservable
        .Timestamp()
        .Buffer(5, 1)
        .Select(l => ((l[4].Timestamp - l[0].Timestamp).TotalMilliseconds / (l[4].Value - l[0].Value)) * (100 - l[4].Value))
        .Select(msRemaining => msRemaining / 1000);
    

    说明:

    对于每个进度更新,

    • .Buffer(5, 1) 发布最近5个进度更新的列表。
    • .Timestamp() 将时间戳钉在每个时间戳上。
    • 第一个 Select 运算符计算最远时间戳和最新时间戳之间的毫秒数,将其除以实现的进度,然后将其乘以剩余进度,输出剩余毫秒数。
    • 最后 选择 除以1000得到剩余秒数。