Доступ к HttpContext.Current из разных потоков
У меня есть приложение С# ASP.NET, которое запускает около 25 различных потоков, выполняющих некоторые методы в классе SiteCrawler.cs.
В HttpContext.Current.Session
Я хочу сохранить результат поиска, сделанный пользователем, и представить его пользователю, когда все потоки закончены. Моя проблема в том, что объект HttpContext.Current
имеет значение null в порожденных потоках, потому что он там не существует.
Какие еще параметры я должен сохранять для пользовательских/сессионных данных без использования сеанса из-за ограничений, когда приложение многопоточно?
Я попытался найти каждый дюйм Stackoverflow, чтобы найти решение, но без везения.
Ответы
Ответ 1
В моем приложении есть много кода, который использует HttpContext.Current
, и я не могу изменить этот код.
worker.DoWork()
из примера ниже использует этот код. И мне пришлось запускать его в отдельном потоке.
Я пришел к следующему решению:
HttpContext ctx = HttpContext.Current;
Thread t = new Thread(new ThreadStart(() =>
{
HttpContext.Current = ctx;
worker.DoWork();
}));
t.Start();
// [... do other job ...]
t.Join();
Ответ 2
Посмотрите на эту статью Fritz Onion: Используйте потоки и создайте асинхронные обработчики в своем веб-коде на стороне сервера. Это довольно долго, но ваше требование не слишком тривиально.
Также К. Скотт Аллен опубликовал несколько более короткую статью по этой самой теме: Работа с HttpContext.Current
Ответ 3
@Rory сделал комментарий выше, что некоторые объекты в HttpContext
станут нулевыми, даже если вы передадите их в Thread. Это случилось со мной с свойством User
. Поэтому вместо этого вы можете скопировать пользователя в поток CurrentPrincipal следующим образом:
В контексте контроллера вы можете отключить пользователя:
_user = HttpContext.Current.User;
var processThread = new Thread(() => ThreadedCode());
processThread.Start();
В потоке установите пользователя "Thread's":
private static void ThreadedCode()
{
// Workaround for HttpContext.Current.User being null.
// Needed for CreatedBy and RevisedBy.
Thread.CurrentPrincipal = _user;
Обратите внимание, что HttpContext будет доступен только для срока службы запроса. Поток будет жить на потенциально намного дольше, чем запрос, и, вероятно, для этого вам нужен поток в первую очередь!:)
Ответ 4
Вы можете сохранить его в базе данных, а затем вы можете позволить браузеру пользователей обновлять или использовать ajax или использовать новый signalr, чтобы проверить, был ли результат уже записан в db. надеюсь, что это поможет.
Ответ 5
Просто добавьте HttpContext.Current к конструктору вашего класса SiteCrawler.cs
public class SiteCrawler
{
HttpContext context = HttpContext.Current;
public void Method()
{
context.WhateverYouWant
}
}