其他分享
首页 > 其他分享> > 异步等待未在预期的线程上执行

异步等待未在预期的线程上执行

作者:互联网

为了理解异步/等待,我制作了一个带有一个按钮的小示例WPF应用程序.当点击它会做一些“工作”:

private async void goButtonClicked(object sender, EventArgs e)
        {

            WhatThreadAmI();
            var task = populateRawData().ConfigureAwait(false);
            WhatThreadAmI();
            BusyIndicator.IsBusy = true;    

            await task;
            WhatThreadAmI(); //this isnt on the main thread - why??
            BusyIndicator.IsBusy = false;

            Console.WriteLine("fin");
        }

“ WhatThreadAmI”只是将当前线程与我在初始化时保存的UI线程进行比较.

public bool IsMainThread => uiThread == Thread.CurrentThread;

我希望它的输出为True-True-True,在填充原始数据方法中使用“ WhatThreadAmI”调用返回false.

实际发生的是True-True-False,填充原始数据方法中的““ WhatThreadAmI”调用返回true.

我知道我必须在这里遗漏一些非常基本的东西,但是有人可以帮我了解发生了什么吗?

解决方法:

var task = populateRawData().ConfigureAwait(false);

ConfigureAwait(false)返回一个已配置的任务等待者,该等待者不会在捕获的上下文中恢复.我在博客上详细解释了how await captures and resumes on context;使用ConfigureAwait(false)表示不捕获上下文并在上下文上恢复.在这种情况下,“上下文”是UI线程.因此,UI线程不会继续等待,因为ConfigureAwait(false)明确告诉等待它不需要.

另外,该代码中的task变量不包含Task.将ConfigureAwait的结果包含在变量中而不是使用其await是非常不寻常的.以下示例是等效的,并且-我认为-可以更清楚地说明正在发生的事情:

WhatThreadAmI();
var task = populateRawData();
WhatThreadAmI();
BusyIndicator.IsBusy = true;    

await task.ConfigureAwait(false);
WhatThreadAmI(); //this isnt on the main thread - why??
BusyIndicator.IsBusy = false;

换句话说,它是ConfigureAwait,而不是ConfigureTask.它根本不会改变任务. ConfigureAwait仅与await一起使用才有意义.

标签:async-await,c
来源: https://codeday.me/bug/20191118/2029589.html