9

Xamarin发布了对async/的支持,await它真正简化了移动平台中响应式 UI 的开发。从现在开始,我想利用它并通过使用 async/await 来提高我的代码的编程水平。

但是,由于我对 C# 比较陌生,并且在我无法在我的代码中找到可以调用方法的“钩子”之前没有使用过async/ 。我知道事件处理程序是典型的地方(发生 IoC 的地方),但想象一下以下场景:awaitasync

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

async Task PerformMyTaskAsync ()
{
    // ...
    await ... // another async API
    // ...
}

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();

    // .. initialize UI
    await PerformMyTaskAsync ();
}

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

当视图控制器加载(或出现,无论如何)时启动后台任务的“替代”方法是什么?

4

3 回答 3

19

最新的 Xamarin 稳定通道版本支持 ViewController 生命周期方法的 Async/Await 重载。尝试:

public async override void ViewDidLoad()
于 2013-08-16T09:05:24.130 回答
0

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

于 2013-08-16T02:45:37.983 回答
0

因此,从事件中从 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 的含义在其他问题中得到了更好的探索,尽管我相信“long”的区别是几毫秒。

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

public override void ViewDidLoad()
{
    base.ViewDidLoad();
    TaskHelper.RunBg(async () => {
        await someBgAsyncMethodGoesHere(arg1, arg2);
    );
}
于 2020-03-23T21:24:16.710 回答