我有一个屏幕,可以从远程服务器检索信息并将该信息显示给用户。我希望在显示屏幕时更新此信息(无需其他用户交互)。
public partial class MyPage : ContentPage
{
protected override async void OnAppearing()
{
base.OnAppearing();
try
{
MyLabel.Text = (await GoGetTheData ()).Stuff;
}
catch (Exception e)
{
MyLabel.Text = "Narg";
}
}
}
这可以接受吗?我已经看到了关于“async void”的邪恶的所有讨论,以及它应该如何仅在事件处理程序中使用,并且这不是一个事件处理程序。
在这种情况下,框架是否保证正常,因为I(1)在获取所有异步之前调用了base.OnAppearing(),并且(2)捕获了我的异常?
答案 0 :(得分:9)
这是可以接受的。由于某种原因,添加了对这些框架覆盖的异步支持。有一些邪恶的" async void"一般而言,但这种情况并不适用。
但请注意,您应确保尽快返回OnAppearing(Forms)
,OnCreate(Android)
和ViewDidLoad(iOS)
方法,以便您的用户获得愉快的体验。
事实上,您会在大量的表单示例中看到这种确切的语法:https://github.com/xamarin/xamarin-forms-samples/search?utf8=%E2%9C%93&q=async+void+OnAppearing
答案 1 :(得分:1)
假设这是对为页面调用Appearing事件的受保护方法的覆盖,那么是的,这很好。
此方法实际上是一个事件,它是在引发事件之前调用的方法。
编辑:正如@apineda在评论中指出的那样,实际情况并非如此。
请注意,在任何事件处理程序运行后,您的异步内容将完成,因为这些是在 base.OnAppearing()
中调用的。
答案 2 :(得分:-1)
如果你正在处理事件(OnAppear essentiallt回调出现),那就完全没问了。
返回类型异步方法应返回Task,Task或 空隙。
如果方法不返回任何其他方法,请指定任务返回类型 值。
如果方法需要返回值,请指定Task,其中 TResult是返回的类型(例如int)。
void返回类型主要用于需要的事件处理程序 它。调用void返回异步方法的代码无法等待 结果。
在可能的情况下使用简短的任务,但在与事件处理程序相关的情况下,只使用void。
如果您需要调用异步,则可以根据此问题使用TaskCompletionSource
Is it possible to await an event instead of another async method?
private TaskCompletionSource<object> continueClicked;
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
// Note: You probably want to disable this button while "in progress" so the
// user can't click it twice.
await GetResults();
// And re-enable the button here, possibly in a finally block.
}
private async Task GetResults()
{
// Do lot of complex stuff that takes a long time
// (e.g. contact some web services)
// Wait for the user to click Continue.
continueClicked = new TaskCompletionSource<object>();
buttonContinue.Visibility = Visibility.Visible;
await continueClicked.Task;
buttonContinue.Visibility = Visibility.Collapsed;
// More work...
}
private void buttonContinue_Click(object sender, RoutedEventArgs e)
{
if (continueClicked != null)
continueClicked.TrySetResult(null);
}
https://developer.xamarin.com/guides/cross-platform/advanced/async_support_overview/
答案 3 :(得分:-3)
我用这种方式
protected override OnAppearing(){
base.OnAppearing();
Task.Run(async()=>{
try
{
// Use VM and Binding...
MyVM.Data = (await GoGetTheData ()).Stuff;
}
catch (Exception e)
{
// Here I think you should use Device.BeginInvokeOnMainThread();
MyVm.Data = "Narg";
}
});
}
某处...
MyText.BindingContext = MyVm;
MyText.SetBinding(Label.TextProperty, "Data");