Async/Await:ConfigureAwait的意外行为

use*_*129 4 c# asp.net asp.net-mvc task-parallel-library async-await

如果在ASP.NET MVC中执行以下代码,您可以在调试窗口中看到await,即使ManagedThreadId发生更改,它也会正确恢复该文件的文化:

public async Task<ActionResult> Index()
{
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-DE");

    Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
    Debug.WriteLine(Thread.CurrentThread.CurrentUICulture);

    await SomeMethod();

    Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
    Debug.WriteLine(Thread.CurrentThread.CurrentUICulture);

    return View();
}

private async Task SomeMethod()
{
    await Task.Delay(100).ConfigureAwait(false);
}
Run Code Online (Sandbox Code Playgroud)

然后我将ConfigureAwait(false)从SomeMethod()移动到Index(),除此之外,它与上面的代码相同:

public async Task<ActionResult> Index()
{
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-DE");

    Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
    Debug.WriteLine(Thread.CurrentThread.CurrentUICulture);

    await SomeMethod().ConfigureAwait(false);

    Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
    Debug.WriteLine(Thread.CurrentThread.CurrentUICulture);

    return View();
}

private async Task SomeMethod()
{
    await Task.Delay(100);
}
Run Code Online (Sandbox Code Playgroud)

现在它不会恢复我的文化,但始终将其设置为new CultureInfo("en-US").但我希望使用这两种方法,结果必须相同.它绝对不清楚,为什么会发生这种情况.

svi*_*ick 7

如果您使用await task.ConfigureAwait(false),那么该方法的其余部分(以及您从那里调用的任何内容)将不会在原始上下文中执行.但这不会影响逻辑调用树中更高的代码.

而且我认为这是实现它的唯一合理方式.如果必须在原始上下文中执行更高的代码(这是非常常见的),那么ConfigureAwait()库内代码深处的某个地方实际上不应该影响它.

为了使其更具体,await如果ConfigureAwait()根据您的行为,以下在Winforms 中使用的简单示例将不起作用:

async void ButtonClicked(object sender, EventArgs e)
{
    textBlock.Text = "Downloading";
    await DownloadAsync();
    textBlock.Text = "Finished";
}

async Task DownloadAsync()
{
    data = await new HttpClient().GetStringAsync(url).ConfigureAwait(false);
}
Run Code Online (Sandbox Code Playgroud)