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异步方法,则会导致死锁,需要重新启动应用程序才能修复。虽然我所拥有的东西有效,但我并不是真正的粉丝。我还有哪些其他选择?
这里的问题不在于如何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)