Как сохранить контекст выполнения потока во время вызова QueueUserWorkItem в ASP.Net? - PullRequest
3 голосов
/ 17 ноября 2011

У нас есть приложение ASP.NET, которое ставит в очередь некоторые из своих длительных операций (например, генерирует отчеты) в ThreadPool с использованием System.Threading.ThreadPool.QueueUserWorkItem.

У нас есть две проблемы с этим подходом:

  1. Мы запускаем пул приложений ASP.Net с использованием определенной учетной записи службы домена, чтобы он мог обращаться к удаленным ресурсам, включая файлы и базы данных. Когда выполнение начинается в ThreadPool, для идентификатора пользователя потока устанавливается значение Сетевая служба, что не позволяет нам получать доступ к удаленным ресурсам.

  2. Доступ к веб-приложению может одновременно осуществляться пользователями в разных странах, а формат данных, которые мы предоставляем каждому пользователю, основан на их настройках культуры (с использованием стандартных настроек глобализации в 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

Ответы [ 2 ]

1 голос
/ 17 ноября 2011

Первое, что вы должны сделать, это рассмотреть , а не с длительным процессом из ASP.NET.Фактически, вы должны попытаться разгрузить любые долго работающие процессы в службу, которой они принадлежат.Служба Windows, WCF и т. Д.

System.Threading.ThreadPool.QueueUserWorkItem(AddressOf Testing, New Object())

Это может быть проблемой для информации, связанной с культурой.Вам нужно будет передать идентификатор методу обратного вызова.

1 голос
/ 17 ноября 2011

Этот метод подписи:

public static bool QueueUserWorkItem(
    WaitCallback callBack,
    Object state
)

Принимает объект состояния. Это может быть экземпляр класса, который содержит культуру вашего пользователя и любые другие элементы, которые вам нужны для сохранения. Эта информация распространяется обратно в метод обратного вызова, где вы можете привести ее обратно к экземпляру вашего класса.

...