4

If you execute the following code in ASP.NET MVC, you can see in Debugging Window that it will correctly restore the thread's culture after await, even if ManagedThreadId changes:

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);
}

Then I just move ConfigureAwait(false) from SomeMethod() to Index(), except for this, it's the same code as above:

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);
}

Now it doesn't restore my culture but always set it to new CultureInfo("en-US"). But I expect that using both methods, the result must be the same. It's absolutely unclear, why it's happening.

4

3 回答 3

7

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

我认为这是唯一合乎逻辑的方法。如果更高层的代码必须在原始上下文中执行(这很常见),那么ConfigureAwait()库代码深处的某个地方真的不应该影响它。

为了使这一点更具体,如果按照您的行为,以下await在 Winforms 中使用的简单示例将不起作用:ConfigureAwait()

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);
}
于 2013-09-24T01:01:19.513 回答
1

您可以创建自己的等待者,以通过await延续回调使文化流动,即使它发生在不同的池线程上。所以,你的电话看起来像:

await SomeMethod().WithCulture();

Stephen Toub 在PFX Team 博客上准确展示了如何做到这一点,请查找CultureAwaiter

于 2013-09-24T06:50:47.070 回答
0

(来自手机)

你不仅失去了线程文化。你正在失去整个背景。

当存在 SynchronizationContext 时,延续将发布到该 SynchronizationContext。在 ASP.NET 中这是一个请求处理程序线程,在客户端 UI 中是 UI 线程。

ConfigureAwait(false) 指示生成的状态机不要发布到捕获的(如果有的话)SynchronizationContext。

索引不应该使用它,但应该从那里调用任何代码。

于 2013-09-25T19:59:25.563 回答