框架覆盖

时间:2017-03-09 18:17:57

标签: c# asynchronous xamarin async-await

我有一个屏幕,可以从远程服务器检索信息并将该信息显示给用户。我希望在显示屏幕时更新此信息(无需其他用户交互)。

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)捕获了我的异常?

4 个答案:

答案 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事件的受保护方法的覆盖,那么是的,这很好。

此方法实际上是一个事件,它是在引发事件之前调用的方法。

编辑:正如@a​​pineda在评论中指出的那样,实际情况并非如此。

请注意,在任何事件处理程序运行后,您的异步内容将完成,因为这些是在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/

https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

https://developer.xamarin.com/guides/ios/user_interface/controls/part_2_-_working_with_the_ui_thread/

答案 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");