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

private async Task ConnectAsync(CancellationToken cancellationToken = default)
{
    ...
}
我正在使用IActivatableViewModel在ViewModel-activation上启动它,如下所示:
// 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是接受取消 token 并返回Task的方法。为了启用this.Events()魔术,您需要使用Pharmacist或安装ReactiveUI.Events软件包之一。但是无论如何,如果您要依赖WhenActivated,也不需要ThrownExceptionsIsExecuting等,那么您的选项也看起来不错。如果您想使用命令并依赖WhenActivated,请修改View.xaml.cs代码:
// View.xaml.cs
this.WhenActivated(disposable => {
    Connect.Execute().Subscribe();
    Disposable
        .Create(() => Cancel.Execute().Subscribe())
        .DisposeWith(disposable);
});
我们不会处理Execute()返回的订阅,因为它们会在命令完成执行后被处理。希望这可以帮助! ✨

关于c# - 如何使用ReactiveUI正确取消ViewView停用任务?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/64124395/

10-16 23:08