如何按顺序 运行 任务并将结果放入 IObservable

How to sequentially run Tasks and put the result in IObservable

在我的 ViewModel 中,我想做几件事,并想在事情完成时更新状态。

Kent Boogaart 的书建议使用 Observable 来显示进度。我现在被困在如何做多项工作,比如在 Tasks 中,然后勾选可观察对象。我尝试了 Concat 运算符,但所有 Task 都立即开始,而不是一个接一个地开始。

public class StartupViewModel : ReactiveObject
{
    public string Status { [ObservableAsProperty]get; }

    public ReactiveCommand<Unit,string> LoadedCommand { get; set; }
    public StartupViewModel()
    {
        var progress = Observable.Concat(
            Task.Run(() =>
            {
                Thread.Sleep(3000);
                return "hello";
            }).ToObservable(),
            Task.Run(() =>
            {
                Thread.Sleep(3000);
                return "cip";
            }).ToObservable(),
            Task.Run(() =>
            {
                Thread.Sleep(3000);
                return "2040";
            }).ToObservable()
        );

        LoadedCommand = ReactiveCommand.CreateFromObservable(() => progress);
        LoadedCommand
            .ToPropertyEx(this, x => x.Status, "Starting up, please be patient");
    }
}

可能你可以像

return Observable.Create<string>(async (obs, cancellationToken) =>
{
   obs.OnNext(await Task1(cancellationToken));
   obs.OnNext(await Task2(cancellationToken));
   obs.OnNext(await Task3(cancellationToken));
   obs.OnCompleted();
});

问题是您正在启动 Concat 构造中的所有任务。 Concat 正在做正确的事情并从所有已完成的任务中获取结果。您想要做的是将任务包装在 Obserable.Defer 中,这样它们就不会一次全部启动,而只会在它们被 Concat 运算符订阅时启动:

var progress = Observable.Concat(
  Observable.Defer (() => Task.Run(() => { Thread.Sleep(5000); return 1; }).ToObservable()),
  Observable.Defer (() => Task.Run(() => { Thread.Sleep(5000); return 2; }).ToObservable())
);