在我的 MVVM 应用程序中,当 ViewModel 被激活时,会启动一个任务来建立网络连接,并且可能需要一些时间才能完成。此任务是可取消的:
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 https://www.reactiveui.net/docs/handbook/commands/)。如果您这样做,您将获得诸如订阅的能力等福利ThrownExceptions
and IsExecuting
observables,然后显示一些加载指示器或错误消息,让用户了解应用程序正在做什么。另外,遵循所描述的模式here https://www.reactiveui.net/docs/handbook/commands/canceling#canceling-via-another-observable,你可以取消它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()
魔法,你需要使用药剂师 https://github.com/reactiveui/pharmacist,或安装其中之一ReactiveUI.Events 事件 https://www.reactiveui.net/docs/handbook/events/包。但无论如何,如果您想依赖的话,您的选择看起来也不错WhenActivated
, 不需要ThrownExceptions
, IsExecuting
等等。如果您想使用命令并依赖WhenActivated
,然后修改View.xaml.cs
code:
// View.xaml.cs
this.WhenActivated(disposable => {
Connect.Execute().Subscribe();
Disposable
.Create(() => Cancel.Execute().Subscribe())
.DisposeWith(disposable);
});
我们不会处理返回的订阅Execute()
因为当命令完成执行时它们无论如何都会被处理。希望这可以帮助! ✨
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)