问题描述
在我的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)。如果执行此操作,则会获得诸如订阅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
是一种接受取消令牌并返回Task
的方法。为了启用this.Events()
魔术,您需要使用Pharmacist或安装ReactiveUI.Events软件包之一。但是无论如何,如果您想依靠WhenActivated
,而不需要ThrownExceptions
,IsExecuting
等,您的选择也很好。如果您想使用命令并依靠{ {1}},然后修改WhenActivated
代码:
View.xaml.cs
我们不会处理// View.xaml.cs
this.WhenActivated(disposable => {
Connect.Execute().Subscribe();
Disposable
.Create(() => Cancel.Execute().Subscribe())
.DisposeWith(disposable);
});
返回的订阅,因为它们会在命令完成执行后被处理。希望这可以帮助! ✨