ReactiveUI:使用 ReactiveCommand.CreateFromObservable() 时,UI 在命令完成之前不会更新

问题描述 投票:0回答:1

我正在将 ReactiveUI 7.0 与 WPF 和 .NET 4.5.2 一起使用。

我正在尝试从 Observable 创建 ReactiveCommand。该代码确实有效,但是,在命令完成之前 UI 不会更新。我有一个进度条和一个进度窗口,我想在命令运行时更新它们。此外,在执行 ReactiveCommand 时,UI 无响应(我无法单击取消按钮或其他任何与此相关的按钮)。我希望这是我所忽视的事情,并且对于比我聪明的人来说是显而易见的。或者也许我只是做错了。

感谢您的浏览。

相关代码如下:

我的 ViewModel 声明:

public ReactiveCommand<Unit, string> PerformSelectedOperationCommand { get; set; }

private StringBuilder sb;

在我的 ViewModel 构造函数中:

PerformSelectedOperationCommand = ReactiveCommand.CreateFromObservable(PerformOperationObservable,
            this.WhenAnyValue(x => x.SelectedPath, x => x.TotalFilesSelected,
                (x, y) => x != null && y > 0));

    // listen to the messages and append to output
    PerformSelectedOperationCommand.Subscribe(s =>
    {
        sb.AppendLine(s);
        ProgressWindowOutput = sb.ToString();
    });

这是我的 ViewModel 中包含的 Observable,它在单击 Go 按钮时运行(注意它正在修改我的 ViewModel 的属性):

private IObservable<string> PerformOperationObservable()
    {
        sb.Clear();
        return Observable.Create<string>((o) =>
        {
            using (cts = new CancellationTokenSource())
            {
                // this creates a copy of the file list which will keep us safe
                // if the user is clicking around on the UI and changing the list.
                var selectedFiles = FileList.Where(x => x.IsChecked).ToArray();
                int total = selectedFiles.Length;
                int count = 0;
                foreach (var file in selectedFiles)
                {
                    ProgressBarMessage = $"Processing {count + 1} of {total}";
                    o.OnNext($"Processing file {file.Name}");
                    SelectedFileOperation.PerformOperation(file.FullPath);
                    count++;
                    PercentComplete = (int)(((double)count / total) * 100);
                    if (cts.IsCancellationRequested)
                    {
                        PercentComplete = 0;
                        ProgressBarMessage = string.Empty;
                        break;
                    }
                }
                ProgressBarMessage = string.Empty;
            }
            o.OnCompleted();
            return Disposable.Empty;
        });
    }
c# reactiveui
1个回答
1
投票

Observable 本质上是单线程的,你需要指定在哪里做工作。我相信你可以做到:

PerformSelectedOperationCommand 
    = ReactiveCommand.CreateFromObservable(
        PerformOperationObservable.SubscribeOn(RxApp.TaskPoolScheduler), // Move subscription to task pool
            this.WhenAnyValue(
                x => x.SelectedPath, 
                x => x.TotalFilesSelected,
                (x, y) => x != null && y > 0
            )
      );

// listen to the messages and append to output
PerformSelectedOperationCommand
    .ObserveOnDispather() // Return to UI thread
    .Subscribe(s =>
    {
        sb.AppendLine(s);
        ProgressWindowOutput = sb.ToString();
    });

您显式订阅任务池上的可观察对象,移动 UI 线程的工作。在使用输出之前,您返回到 UI 线程以便能够在 UI 上进行更新。

© www.soinside.com 2019 - 2024. All rights reserved.