C#/MonoTouch:如何在创建/出现ViewController时调用异步方法

本文关键字:ViewController 出现 调用 异步方法 创建 MonoTouch | 更新日期: 2023-09-27 18:27:48

Xamarin发布了对async/await的支持,这确实简化了移动平台中响应式UI的开发。从现在起,我想利用它,通过使用async/await来提高代码的编程级别

然而,由于我对C#还比较陌生,以前也没有使用过async/await,所以我很难在代码中找到可以调用async方法的"钩子"。我知道事件处理程序是典型的地方(IoC发生的地方),但想象一下以下场景:

我想在加载ViewController时启动后台任务(而不是在按下按钮时启动)。

async Task PerformMyTaskAsync ()
{
    // ...
    await ... // another async API
    // ...
}
public override void ViewDidLoad ()
{
    base.ViewDidLoad ();
    // .. initialize UI
    await PerformMyTaskAsync ();
}

显然,我不能在ViewDidLoad中等待PerformMyTaskAsync,因为ViewDidLoad既不是异步方法,也不是事件处理程序。

当视图控制器加载(或出现,不管怎样)时,启动后台任务的"替代"方法是什么?

C#/MonoTouch:如何在创建/出现ViewController时调用异步方法

最新的Xamarin Stable Channel版本支持ViewController Lifecycle方法的Async/Await重载。尝试:

public async override void ViewDidLoad()

不确定这是否是"最佳"方法,但您是否尝试过从ViewDidLoad()中激发事件,然后在该事件的处理程序中启动异步代码?

因此,在UI线程外,从事件中异步运行一些东西,看起来像这样:

Blah.OnEvent += onEvent;
protected async void onEvent(object sender, EventArgs ev)
{
...
}

void不是一个打字错误——不幸的是,它是Xamarin在异步UI事件中遵循的反模式。

在一些有效的场景中,您希望运行一个使UI等待的异步方法。例如,通过单击按钮来关闭Navigation.PushAsync()。但是,你特别要求一项背景任务,这意味着这可能需要一段时间。为此,您不想让UI等待;您应该启动任务并立即返回。为此,您只需使用与任何C#TPL应用程序中使用的相同的后台任务代码:

    public static void RunBg(Func<Task> fn)
    {
        Task.Run(fn).ConfigureAwait(false);
            // Uncomment to roll up exceptions
            //.GetAwaiter().GetResult();
    }
    public static void RunBgLong(Func<Task> fn)
    {
        Task.Factory.StartNew(fn, TaskCreationOptions.LongRunning).ConfigureAwait(false);
            // Uncomment to roll up exceptions
            //.GetAwaiter().GetResult();
    }

我提供这两者,是因为TPL的创造者已经尽力在引擎盖下提供这两者。2的含义在其他问题中得到了更好的探讨,尽管我认为"长"的区别是一个很小的毫秒数。

所以,你应该像这样开始你的任务:

public override void ViewDidLoad()
{
    base.ViewDidLoad();
    TaskHelper.RunBg(async () => {
        await someBgAsyncMethodGoesHere(arg1, arg2);
    );
}