【问题标题】:Command throws exception when duplicate values are received by Interaction.Handle当 Interaction.Handle 接收到重复值时,命令抛出异常
【发布时间】:2021-01-31 04:32:25
【问题描述】:

我在我的视图模型中实现了以下方法

private async Task OpenAudioFileImpl ()
{
    await OpenFileInteraction.Handle(FileTypes.Audio)
        .Where(fp => !string.IsNullOrWhiteSpace(fp))
        .Where(fp => fp != AudioFilePath)
        .Where(fp => File.Exists(fp))
        .Log(this, $"New audio file path selected")
        .Select(x => AudioFilePath = x);
}

通过这个命令调用:OpenAudioFile = ReactiveCommand.CreateFromTask(async _ => await OpenAudioFileImpl());

在我的视图中注册的处理程序会打开一个Microsoft.Win32.OpenFileDialog,所以我可以选择我想要的文件。

我的目标是仅在选择新文件并且该文件实际存在时更新 AudioFilePath 的值。当我单击按钮时,对话框会正确打开。只要我每次都选择不同的文件,我就不会出错并且AudioFilePath 会正确更新。但是,如果我再次选择相同的文件或取消对话框,该命令将引发异常。我做了一些控制台输出,我很确定问题出在这个方法上,我只是不知道它是什么。

由于它是引发错误的 ReactiveCommand,我知道处理它的唯一方法是:

OpenAudioFile.ThrownExceptions.Subscribe(ex =>
{
    this.Log().Error("OpenAudioFile failed to execute.", ex);
});

我得到的输出是

Exception thrown: 'System.InvalidOperationException' in System.Reactive.dll
Exception thrown: 'System.InvalidOperationException' in System.Private.CoreLib.dll
MainWindowViewModel: OpenAudioFile failed to execute.

这并没有给我太多信息。

【问题讨论】:

  • 如果你把你得到的异常和它抛出的确切行放在一起会有所帮助。
  • @andresantacruz 不幸的是,由于 ReactiveCommands 处理异常的方式,它不会像普通异常一样被抛出。我编辑了我的帖子以显示我对它的了解。

标签: c# wpf reactiveui reactivex


【解决方案1】:

您在这些情况下遇到异常的原因是您使用的是异步等待。等待 observable 的行为是返回最后一个元素(在 OnCompleted 之前),或者抛出观察到的 OnError。但是,如果序列不包含任何元素,您将收到 InvalidOperationException。所以那些 Where 语句过滤掉了唯一发出的元素。

在使用 Rx 时,我更喜欢尽可能避免使用 asnyc/await。但是如果你想坚持使用 async/await,你只需要稍微修改一下你的逻辑。例如,可能会删除 Where 语句并在 Select 中进行条件赋值并在其他地方进行验证。不确定您的整体设置,所以也许您可以想出更好的办法。

【讨论】:

  • 谢谢,我不知道等待可观察对象的这种行为。我认为这不是想要使用 async/await 的问题,而是如果我不使用它们,对话框就不会出现。我按照建议删除了.Where 语句,并且所有工作都按需要进行。
猜你喜欢
  • 2022-01-13
  • 1970-01-01
  • 2014-07-22
  • 1970-01-01
  • 2018-10-18
  • 2017-10-11
  • 1970-01-01
  • 1970-01-01
  • 2013-01-22
相关资源
最近更新 更多