gpt4 book ai didi

c# - CurrentCulture with async/await,自定义同步上下文

转载 作者:可可西里 更新时间:2023-11-01 08:45:01 25 4
gpt4 key购买 nike

我有一个 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;
}
}

你可以这样使用它。在我的简单示例中,它工作正常,但我并没有真正了解评估我的方法的细节(顺便说一句:我的操作系统文化是 de-DE 的)。请注意,这只是示例,与实际代码无关。我刚刚写这篇文章是为了证明 await 之后的文化与 await 之前的文化不同。

    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 或任务在我的情况下好还是不好,我不想展开讨论。

最佳答案

when I created custom tasks to run multiple things in parallel

区分并发(同时做多件事)和并行(使用多个线程同时做多个 CPU 密集型操作)很重要.

I noticed, that within this task the current culture changes after an await.

如果您正在执行并行代码(即,ParallelTask.Run),那么您的操作应该受 CPU 限制,而且它们根本不应该包含 await

避免服务器上的并行代码是个好主意。 Task.Run 在 ASP.NET 上几乎总是一个错误。

您的示例代码在后台线程 (Task.Run) 中执行异步工作 (DownloadStringTaskAsync) 并对其进行同步阻塞 (Wait ).这没有任何意义。

如果您有异步工作要做,那么您可以只使用 async-ready 原语,例如 Task.WhenAll。以下代码在 ASP.NET 上运行时将保留区域性,并将同时执行三个下载:

private async Task TestCultureAsync()
{
Debug.WriteLine(CultureInfo.CurrentCulture);

WebClient client = new WebClient();
string s = await client.DownloadStringTaskAsync(new Uri("http://www.google.de"));

Debug.WriteLine(CultureInfo.CurrentCulture);
}

var task1 = TestCultureAsync();
var task2 = TestCultureAsync();
var task3 = TestCultureAsync();
await Task.WhenAll(task1, task2, task3);

关于c# - CurrentCulture with async/await,自定义同步上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22272970/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com