【问题标题】:Xamarin call async function from override that returns valueXamarin 从返回值的覆盖调用异步函数
【发布时间】:2018-08-06 22:16:10
【问题描述】:

这里的基本设置是我有独立于平台的代码,它可以进行 REST 调用,然后如果发生需要更新 UI 的更改,则调用由平台特定 UI 代码注册的事件处理程序。这些事件处理程序必须在 UI 线程上执行。对于 void 调用,这一切似乎都非常简单,但像这样的情况我不确定我是否做得对:

public override bool FinishedLaunching(UIApplication app,
                                       NSDictionary options) {
    /* Setup code removed */
    Task task = BackendService.DoSomethingAsync();
    return (true);
}

在 iOS 应用程序委托中。这是调用该异步任务并确保在 UI 运行时不暂停 UI 的正确方法吗?它似乎有效,但我不确定它是否会随机爆炸。

【问题讨论】:

  • 你打电话给FinishedLaunching吗?该代码将启动async 操作并在您不知道结果的情况下立即返回。
  • 应用启动时操作系统调用 FinishedLaunching。我只需要启动查询 Web 服务的调用。我只是不确定如果没有等待任务会发生什么。
  • 它将调用您的网络服务并返回。如果您不关心您的调用是否成功,那么您可以将代码保留在那里,如果您确实关心结果,那么您将不得不同步调用您的网络服务或在其他地方进行。
  • 读取FinishedLaunching返回的值需要什么方法?布尔值是如何解释的?

标签: c# ios xamarin async-await


【解决方案1】:

您可以创建一个事件处理程序

private event EventHandler LaunchFinished = delegate { };

然后在FinishedLaunching 方法中订阅并引发事件。

public override bool FinishedLaunching(UIApplication app, NSDictionary options) {
    // subscribe to event with event handler
    LaunchFinished += LaunchFinishedHandler;
    // raise event
    LaunchFinished(this, EventArgs.Empty);        
    return (true);
}

可以等待事件处理程序,因此它不会阻塞 UI 线程

private async void LaunchFinishedHandler(object sender, EventArgs args) {
    LaunchFinished -= LaunchFinishedHandler; //optional

    // Setup code removed for brevity

    //On UI Thread

    await BackendService.DoSomethingAsync(); //non blocking await

    //Back on UI thread
}

事件处理程序是允许async void 的一种情况。使用这种模式还可以让您捕捉到调用异步函数时可能出现的任何异常。

参考Async/Await - Best Practices in Asynchronous Programming

【讨论】:

    【解决方案2】:

    如果您想要“一劳永逸”的异步功能,试试这个;

    public static class TaskExtensions
        {
            /// <summary>       
            /// It is used when you want to call an async method without
            /// awaiting for it. Using this method suppresses the warning CS4014.
            /// </summary>
            /// <param name="task">Task to be called using a fire-and-forget call</param>
            public static void Forget(this Task task)
            {
                task.ConfigureAwait(false);
            }
        }
    

    然后你可以使用它;

    YourActionName().Forget();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-28
      • 1970-01-01
      • 2018-01-03
      • 2022-01-14
      • 2019-02-27
      • 2016-01-14
      相关资源
      最近更新 更多