如何使用ReactiveUI正确取消ViewView停用任务?

问题描述

在我的MVVM应用程序中,当激活viewmodel时,将启动一个Task,该Task建立一个网络连接,并且可能需要一些时间才能完成。此任务是可扩展的:

private async Task ConnectAsync(CancellationToken cancellationToken = default)
{
    ...
}

我正在使用IActivatableviewmodel这样在viewmodel激活中启动它:

// Constructor:
public Someviewmodel(...)
{
    this.WhenActivated(disposable => {
        Observable.StartAsync(ConnectAsync);
    });
}

现在,当在任务完成之前停用viewmodel时,建议取消该长期运行任务的方法是什么?

我想到了这个

this.WhenActivated(disposable => {
    Observable.StartAsync(ConnectAsync).Subscribe().disposeWith(disposable);
});

这是正确的解决方案还是有更好的解决方案?

提前谢谢!

解决方法

是的,您在代码段中显示的代码看起来不错。但是,可能值得将ConnectAsync方法调用移至ReactiveCommand<TInput,TOutput>docs)。如果执行此操作,则会获得诸如订阅ThrownExceptionsIsExecuting可观察对象的特权,然后显示一些加载指示符或错误消息,以使用户随时了解应用程序的运行情况。另外,按照here描述的模式,您可以通过其他命令或事件取消该ReactiveCommand<TInput,TOutput>。通过事件取消看起来像这样:

// ViewModel.cs
Cancel = ReactiveCommand.Create(() => { });
Connect = ReactiveCommand
    .CreateFromObservable(
        () => Observable
            .StartAsync(ConnectAsync)
            .TakeUntil(Cancel));

// View.xaml.cs
this.WhenActivated(disposable => {
    this.Events() // Launch the long-running operation
        .Loaded
        .Select(args => Unit.Default)
        .InvokeCommand(ViewModel,x => x.Connect)
        .DisposeWith(disposable);
    this.Events() // Stop that long-running operation
        .Unloaded
        .Select(args => Unit.Default)
        .InvokeCommand(ViewModel,x => x.Cancel)
        .DisposeWith(disposable);
});

在这里,我假设ConnectAsync是一种接受取消令牌并返回Task的方法。为了启用this.Events()魔术,您需要使用Pharmacist或安装ReactiveUI.Events软件包之一。但是无论如何,如果您想依靠WhenActivated,而不需要ThrownExceptionsIsExecuting等,您的选择也很好。如果您想使用命令并依靠{ {1}},然后修改WhenActivated代码:

View.xaml.cs

我们不会处理// View.xaml.cs this.WhenActivated(disposable => { Connect.Execute().Subscribe(); Disposable .Create(() => Cancel.Execute().Subscribe()) .DisposeWith(disposable); }); 返回的订阅,因为它们会在命令完成执行后被处理。希望这可以帮助! ✨

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...