Как последовательно запустить Tasks и поместить результат в IObservable - PullRequest
1 голос
/ 22 мая 2019

В моей ViewModel я хотел бы сделать пару вещей и хотел бы обновить статус, когда все сделано.

Книга Кента Бугаарта предложила использовать Observable, чтобы показать прогресс. Теперь я застрял в том, как выполнять несколько частей работы, скажем, в Task с, и отметьте наблюдаемое. Я попытался оператор 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");
    }
}

Ответы [ 2 ]

2 голосов
/ 22 мая 2019

Проблема в том, что вы запускаете все задачи внутри конструкции 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())
);
1 голос
/ 22 мая 2019

Потенциально вы могли бы что-то вроде

return Observable.Create<string>(async (obs, cancellationToken) =>
{
   obs.OnNext(await Task1(cancellationToken));
   obs.OnNext(await Task2(cancellationToken));
   obs.OnNext(await Task3(cancellationToken));
   obs.OnCompleted();
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...