我有一个Web应用程序,我使用async / await来使用大量的异步操作。一切都运行良好,但是当我创建自定义任务以并行运行多个事物时,我注意到,在此任务中,当前文化在等待之后发生了变化。问题似乎是,线程池使用操作系统的文化,这与请求的文化不同,并且默认同步不会更新文化,即使在更改任务中当前线程的文化时也是如此。
所以我创建一个自定义同步上下文:
public sealed class CulturePreservingSynchronizationContext : SynchronizationContext
{
private CultureInfo culture;
private CultureInfo cultureUI;
public CulturePreservingSynchronizationContext()
{
GetCulture();
}
public void MakeCurrent()
{
SetCulture();
SynchronizationContext.SetSynchronizationContext(CreateCopy());
}
public override SynchronizationContext CreateCopy()
{
CulturePreservingSynchronizationContext clonedContext = new CulturePreservingSynchronizationContext();
clonedContext.culture = culture;
clonedContext.cultureUI = cultureUI;
return clonedContext;
}
public override void Post(SendOrPostCallback d, object state)
{
base.Post(s =>
{
SetCulture();
d(s);
}, state);
}
public override void OperationStarted()
{
GetCulture();
base.OperationStarted();
}
private void SetCulture()
{
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = cultureUI;
}
private void GetCulture()
{
culture = CultureInfo.CurrentCulture;
cultureUI = CultureInfo.CurrentUICulture;
}
}
你可以像这样使用它。在我的简单示例中,它工作正常,但我没有真正理解评估我的方法的细节(顺便说一下:我的os-culture是de-DE)。请注意,这只是一个示例,与实际代码无关。我刚刚写了这篇文章来证明等待之后的文化与等待之前的文化不同。
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
CulturePreservingSyncContext context = new CulturePreservingSyncContext();
Task.Run(async () =>
{
context.MakeCurrent();
Console.WriteLine(CultureInfo.CurrentCulture);
WebClient client = new WebClient();
string s = await client.DownloadStringTaskAsync(new Uri("http://www.google.de"));
Console.WriteLine(CultureInfo.CurrentCulture);
}).Wait();
我们非常欢迎任何建议了解同步上下文的实现是否良好,如果没有,是否有更好的解决方案。如果async和await或者任务在我的情况下好或不好,我不想打开讨论。