by Michael S. Kaplan, published on 2010/05/23 07:01 -04:00, original URI: http://blogs.msdn.com/b/michkap/archive/2010/05/23/10013884.aspx
Web developer Matt's question was to my way of thinking a very reasonable one:
Is there any way to automatically change the UI culture for every background thread that .NET creates?
At application startup we force the UI culture on the main thread since our application is localized independently of the OS. This works fine for exceptions that we throw from the UI thread – we’ve already forced the culture and so we look up the resource strings in the application language, instead of the OS/.NET language. However, we’ve added a bunch of multithreading this release and noticed that all of the exceptions on the background threads aren’t getting localized since we haven’t forced the culture on those threads.
It would be a LOT of work to go force the thread culture EVERYTIME we create a thread. We’re also using the TPL extensively so it’s not even clear when threads are being created since we’re not explicitly creating them ourselves – the TPL is!
With the move to more parallel applications, this seems like something that other applications must have run into, so I’m wondering if there’s any way to hook into the framework to override the default culture for all new threads?
No. There is currently no way to make this happen. Your option will be store the culture in a static variable and use that culture to load resources on the background thread.
Right – except that once the TPL comes into play I don’t even KNOW when I’m on a background thread or not, or if the culture has already been forced on said thread. It also requires driving knowledge of the application’s localization strategy into EVERY single piece of code that runs in the application – I now have to pepper calls to force the culture like spaghetti all over the place into every single piece of code that could conceivably run on a background thread, which just seems like a terrible, terrible mess.
With the advent of much more parallel programming, this sounds like it could be a nice scenario for the framework to help with by providing me with some way to tell the framework how to force the culture for all new threads.
This is a question that is asked fairly often.
And although I have mentioned in blogs like New for Windows 7: The PROCESS to keep MUI from being THREADbare.... how .Net really could and in fact ought to be doing something better here, another question comes to mind, one that is perhaps due to my Win32 grounding and the straightforward nature of the web applications and sites I have been tasked to design.
In Win32, the UI is by its nature meant to be very single threaded even in the most complex multi-threaded applications. And any time something must be done in another thread complex interactions have to be done for the application to behave reliably.
Thus as big of a fan as I am of the process default user interface language, I hardly need for every thread in a threadpool to be updated since most of those worker threads are probably doing nothing where the user interface language is even relevant.
Now I may be missing something in the web scenario, or perhaps there is some sort of nut-job object oriented purity objection to an object like thread having to know more about some external setting to do its work, but is its really that common for so many worker threads to be doing things that need the UI language, and that retrieving the value is such a bad idea technically?
I mean, I will be happy when they solve the problem, but my happiness is based on a scenario that seems much more defensible to me.
In Matt's scenario, are the errant threads all popping up their own UI every time? I think I have seen those kinds of web sites, the ones that pop up random alerts one on top of the next, without waiting for me to respond. My rule is to avoid those kind of sites, but maybe that is just me....
In the world of a complex web application that spans multiple servers and has thousands or tens of thousands of clients, each client's settings that are relevant to work done for the client will have to obtain whatever settings they need -- and language is just another of these settings that a lowly threadpool thread will have to obtain to do its work.
Is there some other scenario I am unaware of?
What am I missing here?
Cheong on 24 May 2010 11:21 PM:
For web applications, it's not uncommon to have culture related routine poping around everywhere (especially true if the pages are ported from PHP/ASP)
It's fairly uncommon for web applications written in languages with no MVC like framework (i.e.: that includes .NET v1.x sites... Oh memories of those home-grown AJAX before AJAX frameworks are available...) to have clean seperation of logic and presentation related stuffs.
P.S.: Seems the size of "post" button is wrong. The button now is broken into 3 parts.
David Kean on 24 May 2010 11:55 PM:
Even though you may not be showing UI on other threads, you might be generating messages to be displayed on the UI thread. For example, let's say you're opening a file on a background thread, you probably going to be pushing any errors from System.IO back to the UI thread. You will want these in the same locale that your UI is running under.
Michael S. Kaplan on 25 May 2010 7:34 AM:
I have yet to a single exception error message that I would want to show as is to a user in ANY language -- which suggests that I would be unhappy with any application that was not handling the exception and if required throwing one's own "translated into something understandable" one, instead....
Michael S. Kaplan on 25 May 2010 9:42 AM:
I've discussed the similar issue in the context of .NET and SQL Server in blogs like More on locales in SQL Server. And pretty much come to the same conclusion....
dbacher on 25 May 2010 1:14 PM:
Are you sure this is a web application? .NET is used for a lot else, and ThreadPool would be typical of WinForms, WPF, Services, or a Console App -- it would be unusual to use ThreadPool in ASP.NET (although not impossible).
Anyway -- if it is ASP.NET, there is not one line of user code that runs before ThreadPool is initialized and threads are already created and running. ASP.NET uses thread pools, and they are active before any piece of user code in an ASP.NET app runs.
If it is the other technologies, static/shared initializers and constructors run before user code gets a chance to do anything, as well, and can conceptually queue items on the thread pool.
Additionally, you borrow the thread from the ThreadPool -- your work item does not own the thread, and it is not re-initialized when you return it. Windows, COM, .NET and even other processes (Visual Studio, for example) can and do borrow threads from your process' pool, and can leave the thread in an unknown state. Since the whole point of ThreadPool is to avoid unnecessary initialization or teardown, you're responsible for intiializing and tearing down anything you need to be.
Ideally, you encapsulate (using a closure, class, or global-equivalent) your state separately from the thread, and leave the thread global state alone. Ideally, since you don't own the thread, you don't do anything to it.
Also, ideally, you don't use ThreadPool if you are CPU bound. If you're wanting to leverage all 4 cores, you are much better off writing your own threading code than using ThreadPool in almost all CPU-bound cases. (that's because of how ThreadPool is designed).
go to newer or older post, or back to index or month or day