C# 如何使用ReactiveUI正确取消ViewModel停用时的任务?

C# 如何使用ReactiveUI正确取消ViewModel停用时的任务?,c#,mvvm,system.reactive,reactiveui,C#,Mvvm,System.reactive,Reactiveui,在我的MVVM应用程序中,当一个ViewModel被激活时,一个任务开始建立网络连接,可能需要一些时间才能完成。此任务是可取消的: private async Task ConnectAsync(CancellationToken cancellationToken = default) { ... } 我使用IActivatableViewModel在ViewModel激活时启动它,如下所示: // Constructor: public SomeViewModel(...) {

在我的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
()。如果你这样做,你会得到一些额外的好处,比如订阅
ThrownExceptions
IsExecuting
observables,然后显示一些加载指示器或错误消息,让用户了解应用程序正在做什么。此外,按照描述的模式,您可以通过另一个命令或事件取消该
ReactiveCommand
。通过事件取消将如下所示:

//ViewModel.cs
Cancel=ReactiveCommand.Create(()=>{});
Connect=反应命令
.CreateFromObservable(
()=>可观察
.StartAsync(ConnectAsync)
.TakeUntil(取消));
//View.xaml.cs
当激活时(一次性=>{
this.Events()//启动长时间运行的操作
.装载
.Select(args=>Unit.Default)
.InvokeCommand(ViewModel,x=>x.Connect)
.处置(一次性);
this.Events()//停止长时间运行的操作
.卸货
.Select(args=>Unit.Default)
.InvokeCommand(ViewModel,x=>x.Cancel)
.处置(一次性);
});
这里,我假设
ConnectAsync
是一种接受取消令牌并返回
任务的方法。要启用
this.Events()
magic,您需要使用或安装其中一个软件包。但是无论如何,如果您希望在激活时依赖
ThrownExceptions
IsExecuting
等,那么您的选项看起来也不错。如果您希望使用命令并依赖
WhenActivated
,那么请修改
视图.xaml.cs
代码:

//View.xaml.cs
当激活时(一次性=>{
Connect.Execute().Subscribe();
可任意处理的
.Create(()=>Cancel.Execute().Subscribe())
.处置(一次性);
});

我们不会处理由
Execute()
返回的订阅,因为当命令完成执行时,它们无论如何都会被处理掉。希望这有帮助!✨

我想没问题,非常感谢,我喜欢这个解决方案,它更强大、更干净。但因为我使用的是Avalonia UI,我可能不得不等待在下一次预览中发布。在阿瓦隆尼亚的情况下,我可以使用哪种事件?加载/卸载在那里似乎不存在?AttachedToVisualTree?
启动时
在引擎盖下使用
AttachedToVisualTree
,因此在您的情况下,
我想不需要这个.Events()
。另外,
this.Events()
如果您像这样安装
Pharmacialist
,将变得可用。同样
Avalonia.ReactiveUI.Events
也应该在Avalonia每晚构建提要中可用