ReactiveUI - 如何管理 ReactiveCommand 异常?

发布于 2025-01-09 04:32:50 字数 1561 浏览 0 评论 0原文

我有一个简单的用户控件,其中包含 ViewModel 和 ReactiveCommand CheckForUpdates ,它在后台运行并可能会抛出异常。该命令在 ViewModel 的 WhenActivated 方法中显式执行。我想要实现的就是捕获异常并将其记录在 ViewModel 中,并向用户另外显示消息框。问题是,当我添加 Catch 时,ThrownExceptions 不会返回任何内容,并且不会显示 MessageBox。当我删除 Catch 时,应用程序崩溃...我不知道如何正确执行此操作?

public partial class SettingsDialog : SettingsDialogBase, IDialog
{
    public SettingsDialog()
    {
        InitializeComponent();

        this.WhenActivated((CompositeDisposable d) =>
        {
            ViewModel
                .CheckForUpdates
                .ThrownExceptions
                .Subscribe(ex =>
                {
                    MessageBoxHelper.ShowError(ex); // doesn't fire when `Catch` is present in ViewModel
                })
                .DisposeWith(d);
        });
    }
}



ViewModel:

public ReactiveCommand<Unit, ApplicationUpdateInfo> CheckForUpdates { get; set; }

public SettingsDialogViewModel(IApplicationUpdateService updateService)
{
    CheckForUpdates = ReactiveCommand.CreateFromTask(async () =>
    {
        return await CheckForUpdatesAsync();
    });

    this.WhenActivated((CompositeDisposable d) =>
    {
        CheckForUpdates
            .Execute()
            .Catch(Observable.Return(new ApplicationUpdateInfo())) // crashes the app if removed
            .Subscribe()
            .DisposeWith(d);
    });
}

    private async Task<ApplicationUpdateInfo> CheckForUpdatesAsync()
    {
        throw new Exception("Error");
    }

I have simple user control with a ViewModel and a ReactiveCommand CheckForUpdates which runs in background and may throw. This command is explicitly executed in ViewModel's WhenActivated method. All I want to achieve is to catch the exception and log it in ViewModel, and additionally show Message Box to the user. The problem is, when I add Catch, then ThrownExceptions doesn't return anything and the MessageBox is not shown. When I remove Catch, the application crashes... I don't know how to do this properly??

public partial class SettingsDialog : SettingsDialogBase, IDialog
{
    public SettingsDialog()
    {
        InitializeComponent();

        this.WhenActivated((CompositeDisposable d) =>
        {
            ViewModel
                .CheckForUpdates
                .ThrownExceptions
                .Subscribe(ex =>
                {
                    MessageBoxHelper.ShowError(ex); // doesn't fire when `Catch` is present in ViewModel
                })
                .DisposeWith(d);
        });
    }
}



ViewModel:

public ReactiveCommand<Unit, ApplicationUpdateInfo> CheckForUpdates { get; set; }

public SettingsDialogViewModel(IApplicationUpdateService updateService)
{
    CheckForUpdates = ReactiveCommand.CreateFromTask(async () =>
    {
        return await CheckForUpdatesAsync();
    });

    this.WhenActivated((CompositeDisposable d) =>
    {
        CheckForUpdates
            .Execute()
            .Catch(Observable.Return(new ApplicationUpdateInfo())) // crashes the app if removed
            .Subscribe()
            .DisposeWith(d);
    });
}

    private async Task<ApplicationUpdateInfo> CheckForUpdatesAsync()
    {
        throw new Exception("Error");
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

吐个泡泡 2025-01-16 04:32:50

您应该在抛出异常之前订阅ThrownExceptions

您通常在视图模型的构造函数中执行此操作:

CheckForUpdates.ThrownExceptions.Subscribe(ex => ...);

如果您想在视图中订阅 ThrownExceptions,您需要在视图模型抛出之前执行此操作,例如:

var subscription = ViewModel?.
    CheckForUpdates.
    ThrownExceptions.
    Subscribe(ex => MessageBoxHelper.ShowError(ex));

this.WhenActivated((CompositeDisposable d) =>
    subscription.DisposeWith(d));

You should subscribe to ThrownExceptions before the exception is thrown.

You typically do this in the constructor of the view model:

CheckForUpdates.ThrownExceptions.Subscribe(ex => ...);

If you want to subscribe to ThrownExceptions in the view, you need to do it before the view model throws, e.g.:

var subscription = ViewModel?.
    CheckForUpdates.
    ThrownExceptions.
    Subscribe(ex => MessageBoxHelper.ShowError(ex));

this.WhenActivated((CompositeDisposable d) =>
    subscription.DisposeWith(d));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文