Seb*_*hle 11 c# multithreading task-parallel-library
我有一个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;
}
}
Run Code Online (Sandbox Code Playgroud)
你可以像这样使用它.在我的简单示例中它工作正常,但我没有真正理解评估我的方法的细节(顺便说一句:我的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();
Run Code Online (Sandbox Code Playgroud)
我们非常欢迎任何建议,了解同步上下文的实现是否良好,如果没有,是否有更好的解决方案.如果异步和等待或任务在我的情况下好或不好,我不想打开讨论.
当我创建自定义任务以并行运行多个事物时
区分并发(同时执行多个操作)和并行(使用多个线程同时执行多个CPU绑定操作)非常重要.
我注意到,在这项任务中,当前的文化在等待之后发生了变化.
如果您正在执行并行代码(即,Parallel或Task.Run),那么您的操作应该受CPU限制,并且它们根本不应包含await任何内容.
避免服务器上的并行代码是个好主意.Task.Run在ASP.NET上几乎总是一个错误.
您的示例代码DownloadStringTaskAsync在后台线程(Task.Run)中执行异步work()并同步阻塞它(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);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2892 次 |
| 最近记录: |