3

I have a .NET MVC/WebApi app which sets up Culture for the current thread during the ASP.NET AcquireRequestState event (we use custom logic to determine the preferred ui culture for each of our users). While this works for synchronous cases, I'm concerned that it will not work when using async or explicit multi- or background-threading (such as using Task.Run()).

Unlike Thread.CurrentPrincipal, which flows with the logical flow of control, culture seems to simply flow with the thread:

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(FigureOutUsersCulture());
Task.Run(() => Thread.CurrentThread.CurrentUICulture.Dump()); // en-US

What's the most robust way to set up culture for such an application?

Note: I am not excited about any answer that requires every developer who uses async/await or other threading to remember to initialize the culture. If possible, I'd like something robust across async/await. If this is truly impossible, I'd also accept that answer of course.

EDIT: I understand that using Task.Run() has issues in ASP.NET if you don't wait for the task during a request thread. That said, I am trying to write the infrastructure to set this up in the most robust way possible. I don't know what other developers will do, so if I can be set up for it, I'd like to be.

EDIT: A note about the posted "possible duplicates". I agree that both of these questions are related, but they are not the same! One asks about setting one culture for the whole app, which is the opposite of what I'm trying to do. The other tackles setting culture for MVC3-style async controllers, which is a small (and, to me, largely irrelevant) subset of what I'd like to accomplish.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
ChaseMedallion
  • 20,860
  • 17
  • 88
  • 152

2 Answers2

2

Kyle's advice of delegating culture invariant jobs to other threads (or scheduled in the app pool) is sane. If the job does need to know about culture, pass it along as a parameter.

Simply using await without any fancy tricks like ConfigureAwait(false) will preserve both HttpContext and thread culture across continuations, so i'd go with that*. I have not seen any AspNetSynchronizationContext perfomance related issues (https://stackoverflow.com/a/13494570/289992) and the reason you chose c# is to enjoy its productivity benefits.

*You may consider ConfigureAwait(false) if you are writing library code though. Again you'd make sure that all 'normally ambient' info (Context.Current, CurrentUICulture etc.) is passed in as parameters. Also there are some nice tricks around like this here CultureAwaiter, maybe you could make something out of it. And maybe you'll want to read on the costs and decide for your self if implementing those optimizations is worth your time or not.

Community
  • 1
  • 1
bottlenecked
  • 2,079
  • 2
  • 21
  • 32
0

Given the "possible duplicate" comments, I'm not sure there's a better answer than what EZI said. If you want to create a new thread, you need to tell it about the culture.

A better question might be why you need a culture in other threads? Make those threads do work for you, and then when you get back to the main thread, you can convert information to strings or what-have-you. This might not be appropriate, as I don't know what the threads exactly are doing.

Kyle W
  • 3,702
  • 20
  • 32
  • What about async controllers? Does ASP.NET do some magic to make culture flow properly across await boundaries? What if ConfigureAwait(false) is used? – ChaseMedallion Aug 21 '14 at 19:35