我们有一个ASP.NET应用程序,使用ThreadPool
将一些长期运行的操作(例如,生成报告)排入System.Threading.ThreadPool.QueueUserWorkItem
。
这种方法存在两个问题:
我们使用特定的域服务帐户运行ASP.Net应用程序池,以便它可以访问远程资源,包括文件和数据库。当在ThreadPool中开始执行时,线程的用户标识被设置为Network Service,这不允许我们访问远程资源。
同时可以由不同国家/地区的用户访问Web应用程序,我们为每个用户提供的数据格式基于其文化设置(使用web.config中的标准全球化设置)。当排队的线程启动时,它也丢失了这些信息并恢复到操作系统的默认文化。
现在,我们可以通过捕获状态对象中的当前用户身份和文化并将其传递给后台工作程序来解决大多数这些问题,然后模拟用户并在线程上设置文化,但这似乎是解决这个问题的一种非常“不干净”的方式。
有更好的方法吗?
以下是web.config
的全球化设置:
<globalization requestEncoding="utf-8" responseEncoding="utf-8" culture="auto" enableClientBasedCulture="true" uiCulture="auto"></globalization>
处理请求时,ASP.NET会自动将当前线程的Culture
和UICulture
设置为用户请求的文化(由Accept-Language
中的浏览器自动传递头)。
可以通过将以下代码添加到后面代码中的任何事件(即按钮单击,页面加载等)来复制此行为:
' 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
答案 0 :(得分:1)
此方法签名:
public static bool QueueUserWorkItem(
WaitCallback callBack,
Object state
)
接受状态对象。这可以是保存用户文化的类的实例,以及您需要保留的其他任何项目。此信息将传播回回调方法,您可以将其强制转换回类的实例。
答案 1 :(得分:1)
您应该做的第一件事是考虑不从ASP.NET运行一个长时间的进程。实际上,您应该尝试将任何长时间运行的进程卸载到它所属的服务。 Windows服务,WCF等
System.Threading.ThreadPool.QueueUserWorkItem(AddressOf Testing, New Object())
这可能是文化相关信息的问题。您必须将标识传递给回调方法。