【问题标题】:C# Waiting for all Async tasks to complete when calling from a non-async methodC#从非异步方法调用时等待所有异步任务完成
【发布时间】:2020-08-05 13:43:35
【问题描述】:
我在 Xamarin Forms 项目的构造函数中有以下代码 - 我希望在调用 ShowPage() 方法之前完成每个步骤(它基本上是从 Web 服务加载数据) - 这会工作还是有更好的方法实现这一目标?
public MyTabbedPage()
{
....
Task.Run(async () => await vm1.LoadData();
Task.Run(async () => await vm2.LoadData();
Task.Run(async () => await vm3.LoadData();
ShowPage();
....
} ```
【问题讨论】:
标签:
xamarin
asynchronous
xamarin.forms
async-await
task
【解决方案1】:
在同步函数中不正确地调用异步任务可能会出现问题,因为如果在任务中引发异常,它会抑制详细信息。因此,正确实施这一常见问题至关重要。
您可以使用位于 TaskHelpers.cs 下的 Helpers 文件夹中的 FireAndForget 助手,定义如下:
public static async void FireAndForgetSafeAsync(this Task task, Action<Exception> handleErrorAction = null)
{
try
{
await task.ConfigureAwait(true);
}
catch (Exception ex)
{
handleErrorAction?.Invoke(ex);
}
}
然后,回到你的构造函数中,你可以这样做:
public MyTabbedPage()
{
vm1.LoadData().FireAndForgetSafeAsync(HandleErrorInternal);
vm2.LoadData().FireAndForgetSafeAsync(HandleErrorInternal);
vm3.LoadData().FireAndForgetSafeAsync(HandleErrorInternal);
ShowPage();
}
private void HandleErrorInternal(Exception ex)
{
DisplayAlertAsync("Error", ex.ToString(), "OK").FireAndForgetSafeAsync(HandleErrorInternal);
}
【解决方案2】:
始终尽量避免在构造函数中加载数据。只是一个好习惯。
放到 OnAppearing 方法中,改成 async。
protected override async void OnAppearing()
{
await vm1.LoadData()
await vm2.LoadData()
await vm3.LoadData()
base.OnAppearing();
}