如何在Xamarin Android活动回调中使用await

Den*_*s K 8 c# android asynchronous xamarin.android xamarin

标题可能有点误导,我的问题更多的是为什么它以这种奇怪的方式工作.

所以我有一个具有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
        });
    }
Run Code Online (Sandbox Code Playgroud)

它的工作原理在某种意义上说它没有错误地执行.但是,活动显示为空白屏幕,即使文本视图仅在一定延迟后呈现.因此看起来任务实际上并非异步运行.在"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);
    }
Run Code Online (Sandbox Code Playgroud)

所以问题是,为什么不呢

await SetupData().ConfigureAwait(false); 
Run Code Online (Sandbox Code Playgroud)

解锁流量?为什么我们必须强制延迟异步操作的开始以让UI完成渲染,尽管如此(根据http://www.wintellect.com/devcenter/paulballard/tasks-are-still-not-threads-and -async-is-not-parallel)SetupData应该可以在这里作为一个单独的线程运行?

ps删除在适配器上设置数据的代码不会影响此行为 - 在呈现屏幕之前仍有延迟.所以我不在这里展示代码.

Sus*_*ver 16

通过在UI Looper中等待,您在SetupData方法运行时阻止了线程上的进一步代码执行.

非阻塞示例:

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        SetContentView(Resource.Layout.Main);
        Task.Run(() => SetupData());
        Console.WriteLine("UI Thread / Message Looper is not blocked");
    }

    void SetupData()
    {
        Task.Run(async () =>
        {
            Console.WriteLine($"Are we on the UI thread? {Looper.MainLooper.Thread == Looper.MyLooper()?.Thread}");
            // Simulate a long running task
            await Task.Delay(TimeSpan.FromSeconds(10));
            Console.WriteLine("Done fetching/calculating data");
            RunOnUiThread(() =>
            {
                // Update the data fetched/calculated on the UI thread;
                Console.WriteLine($"Are we on the UI thread? {Looper.MainLooper.Thread == Looper.MyLooper().Thread}");
            });
        }).Wait();
        Console.WriteLine("Done w/ SetupData");
    }
Run Code Online (Sandbox Code Playgroud)

输出:

UI Thread / Message Looper is not blocked
Are we on the UI thread? False
Done fetching/calculating data
Are we on the UI thread? True
Done w/ SetupData
Run Code Online (Sandbox Code Playgroud)