标题可能有点误导,我的问题更多的是关于为什么它以这种奇怪的方式工作。
我有一个包含TextView和ListView的布局的活动。我有一个长时间运行的异步方法来准备要在列表中显示的数据。所以最初的代码是这样的:
protected async override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.MyView);
await SetupData();
}
private async Task SetupData(){
Task.Run(async () => {
var data = await new SlowDataLoader().LoadDataAsync();
// For simplicity setting data on the adapter is omitted here
});
}
它可以运行,也就是说没有出现错误。然而,该活动显示为空白屏幕,即使文本视图只有在一定的延迟后才呈现。因此,任务实际上并没有异步运行。在两个"await"调用上设置ConfigureAwait(false)并没有帮助。将SetupData()调用移动到OnPostCreate、OnResume和OnPostResume中也没有效果。唯一让TextView立即出现并在数据到达后后渲染列表的方法是:
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.MyView);
new Handler().PostDelayed(async ()=>{
await SetupData();
}, 100);
}
所以问题是,为什么不呢?
await SetupData().ConfigureAwait(false);
解锁流程?为什么我们要强制延迟异步操作的启动,以便让UI完成渲染,尽管(根据此http://www.wintellect.com/devcenter/paulballard/tasks-are-still-not-threads-and-async-is-not-parallel)SetupData应该能够在这里作为单独的线程运行?
附注:删除设置适配器数据的代码不会影响此行为 - 屏幕渲染仍然会有延迟。所以我在这里没有展示那段代码。
Task.Run
,所以等待的操作正在另一个线程上运行,但是等待的方法和线程已被挂起,直到等待的操作返回。 - SushiHangover