代码之家  ›  专栏  ›  技术社区  ›  JOTN

从返回值的重写调用异步函数

  •  1
  • JOTN  · 技术社区  · 6 年前

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

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

    在iOS应用程序委托中。这是调用异步任务并确保在运行时不保留UI的正确方法吗?它看起来很管用,但我不确定它是否会在线路上随机爆炸。

    2 回复  |  直到 6 年前
        1
  •  1
  •   Nkosi    6 年前

    可以创建事件处理程序

    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
  •  0
  •   Tolga Kartal    6 年前

    如果你想要一个“fire and forget”异步特性,试试这个;

    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();