在我的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)。如果这样做,您将获得诸如订阅ThrownExceptions
和IsExecuting
可观察项的特权,然后显示一些加载指示符或错误消息,以使用户随时了解应用程序的运行状况。另外,按照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
,也不需要ThrownExceptions
,IsExecuting
等,那么您的选项也看起来不错。如果您想使用命令并依赖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/