We have an ASP.NET application that queues some of its long-running operations (generating reports, for example) into the ThreadPool using System.Threading.ThreadPool.QueueUserWorkItem.
We have two problems with this approach:
-
We run the ASP.Net application pool using a specific domain service account so that it can access remote resources, including files and databases. When the execution starts in the ThreadPool, the user identity of the thread is set to Network Service, which doesn’t allow us to access the remote resources.
-
The web application can be accessed by users in different countries simultaneously and the format of the data that we provide to each user is based on their culture settings (using the standard globalization settings in web.config). When the queued thread is started, it has also lost this information and reverts to the default culture for the operating system.
Now, we can probably get around most of these issues by capturing the current user identity and culture in a state object and passing that to the background worker, then impersonate the user and set the culture on the thread, but this seems like a very "unclean" way to resolve this issue.
Is there a better way?
Additional information:
Here are the globalization settings from web.config:
<globalization requestEncoding="utf-8" responseEncoding="utf-8" culture="auto" enableClientBasedCulture="true" uiCulture="auto"></globalization>
When a request is processed, ASP.NET automatically sets the Culture and UICulture of the current thread to the user’s requested culture (which is passed automatically by the browser in the Accept-Language header).
This behavior can be replicated by adding the following code to just about any event in the code behind (i.e. button click, page load, etc):
' Called from just about anywhere
ThreadInitiator()
Private Sub ThreadInitator()
' Observe the culture and windowsidentity here; they will be correct
System.Threading.ThreadPool.QueueUserWorkItem(AddressOf Testing, new Object)
End Sub
Private Sub Testing(state As Object)
' Observe the culture and windowsidentity here; they will not be what we need them to be
End Sub
This method signature:
Accepts a state object. This can be an instance of a class that hold your user’s culture and whatever other items you need to persist. This information is propagated back into the callback method, where you can cast it back to an instance of your class.