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
既不是异步方法,也不是事件处理程序。
当视图控制器加载(或出现,不管怎样)时,启动后台任务的"替代"方法是什么?
最新的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);
);
}