MVVM Light 调用属性上的异步方法已更改?

JD *_*vis 5 c# wpf mvvm mvvm-light async-await

所以我做了很多挖掘,但在任何地方都找不到任何真正明确的答案。

我正在使用 MVVM Light 和 WPF 编写一个应用程序。我有一个服务注入到我的 ViewModel 中,用于检查所设置的某个属性的有效性。该服务进行网络调用,并且是异步的。该调用不需要停止应用程序的执行,它只是向用户提供有关输入值有效性的视觉反馈。

因此,我设法将一些东西组合在一起以使其正常工作,但感觉有点hackey。

在属性更改时执行异步方法而不诉诸类似方法的正确方法是什么async void

这是我目前所拥有的。

    public string OmmaLicenseNumber
    {
        get => _ommaLicenseNumber;
        set
        {
            Set(() => OmmaLicenseNumber, ref _ommaLicenseNumber, value);
            Patient.OmmaLicenseNumber = value;

            var _ = CheckLicenseValid();
        }
    }

    private async Task CheckLicenseValid()
    {
        var valid = await _licenseValidationService.IsValidAsync(OmmaLicenseNumber);

        // We don't want the UI piece showing up prematurely. Need 2 properties for this;
        LicenseValid = valid;
        LicenseInvalid = !valid;
    }
Run Code Online (Sandbox Code Playgroud)

如果我只是尝试调用.Result异步方法,则会导致死锁,需要重新启动应用程序才能修复。虽然我所拥有的东西有效,但我并不是真正的粉丝。我还有哪些其他选择?

AAA*_*ddd 2

这里的问题不在于如何async在不被观察的情况下运行任务,而在于如何处理异常。我这样说是因为当任务清理完毕时它们可能会出现。

理想情况下,只需向下一位读者展示他们将得到什么。既然你反对使用async void.

选项1

// running an async method unobserved 
Task.Run(async () =>
{
   try
   {
      await DoSomethingAsync();
   }
   catch (Exception e)
   {
       // Deal with unobserved exceptions 
       // or there will be dragons
   }  
});
Run Code Online (Sandbox Code Playgroud)

注意:这在技术上是卸载(它会丢失上下文,请注意)并且asynclamda 无论如何都会使其成为 async void,但是无论如何你都必须处理异常

选项 2以及更具争议性的选项:

public async void DoSomethingFireAndForget()
{
   try
   {
      await DoSomethingAsync();
   }
   catch (Exception e)
   {
      // Deal with unobserved exceptions 
      // or the will be dragons
   }  
}
Run Code Online (Sandbox Code Playgroud)

选项 3两全其美:

注意:使用您需要的任何管道来观察异常,即Action

public static class TaskUtils
{

#pragma warning disable RECS0165 // Asynchronous methods should return a Task instead of void
   public static async void FireAndForgetSafeAsync(this Task task,  Action<Exception> onErrors = null)
#pragma warning restore RECS0165 // Asynchronous methods should return a Task instead of void
   {
      try
      {
         await task;
      }
      catch (Exception ex)
      {
         onErrors?.Invoke(ex);
      }
   }
}
Run Code Online (Sandbox Code Playgroud)