2013-09-23 536 views
4

的意外行为如果您执行在ASP.NET MVC下面的代码,你可以在调试窗口,它将正确恢复线程的文化await后,即使ManagedThreadId变化看:异步/等待:ConfigureAwait

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

然后我刚从的someMethod()以索引()移动ConfigureAwait(假的),除了这一点,这是与上面相同的代码:

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

现在不恢复我的文化却始终将其设置为new CultureInfo("en-US")。但我期望使用这两种方法,结果必须相同。现在还不清楚,为什么会这样。

+0

'ConfigureAwait(true)'做了什么? 'bool'参数控制是否“封送原始上下文” - 是不是你想要的? –

+0

我预计如果将'ConfigureAwait(false)'添加到'await',它会影响整个异步调用链,而不仅仅是当前的方法,因为否则使用它的性能好处很小。 – user1224129

回答

5

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

我认为这是实现它的唯一合乎逻辑的方法。如果上面的代码必须在原始上下文中执行(这很常见),那么ConfigureAwait()库代码内部的某处应该不会影响它。

要根据你使这更具体的,使用的WinForms await是行不通的下面这个简单的例子,如果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); 
} 
1

您可以创建自己的awaiter,以与await文化流继续回调,即使它发生在不同的池线程上。所以,您的通话将类似于:

await SomeMethod().WithCulture(); 

斯蒂芬Toub显示究竟是如何做到这一点的PFX Team blog,寻找CultureAwaiter

0

(来自手机)

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

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

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

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