Parallel.ForEach错误HttpContext.Current

这个方法 – doDayBegin(item.BranchId)需要很长时间才能执行。 所以我使用Parallel.ForEach执行它。 当我使用正常的foreach循环时它的工作正常,但当我使用Parallel.ForEach它显示此错误
你调用的对象是空的。

  public ActionResult Edit([DataSourceRequest] DataSourceRequest request) { try { JavaScriptSerializer js = new JavaScriptSerializer(); List _listDB0010020Vm = new List(); string dataDB0010020vm = Request.Form["griddetailsvm"]; if (!string.IsNullOrEmpty(dataDB0010020vm)) { _listDB0010020Vm = js.Deserialize<List>(dataDB0010020vm). Where(d => d.IsValid == "YES").ToList(); } DateTime start = DateTime.UtcNow; Parallel.ForEach(_listDB0010020Vm, item => { doDayBegin(item.BranchId); }); DateTime end = DateTime.UtcNow; TimeSpan duration = end - start; return Json(new { success = true, message = "Day Begin Process Completed Successfully!" + duration }); } catch (Exception e) { return Json(new { success = false, message = e.Message }); } } public void doDayBegin(int BranchId) { var httpContext = System.Web.HttpContext.Current; IDB0010020Repository _idDB0010020Repository = new DB0010020Repository(); IDB0010044Repository _idDB0010044Repository = new DB0010044Repository(); EBS.DAL.Model.DB0010020 branchDetails = _idDB0010020Repository.FindOne(d => d.BranchId == BranchId); if (branchDetails == null) { ModelState.AddModelError("", "Branch not found!"); } else { try { DateTime LastOpenDate = DateTime.ParseExact(Request.Form["LastOpenDate"].ToString(), "dd/MM/yyyy", CultureInfo.InvariantCulture); // branchDetails.LastOpenDate = LastOpenDate; // branchDetails.LastOpenDate = Convert.ToDateTime(Request.Form["LastOpenDate"].ToString()); } catch (Exception e) { // branchDetails.LastOpenDate = Convert.ToDateTime("2014-07-25 00:00:00.000"); } OperationStatus status = _idDB0010020Repository.UpdateAndSave(branchDetails); if (status != null && !status.Status) ModelState.AddModelError("Updation failed", status.ExceptionMessage); } EBS.DAL.Model.DB0010044 dayBegin = new DB0010044(); dayBegin.BankId = 1; dayBegin.BranchId = BranchId; dayBegin.DayBeginFlag = 1; //added d DateTime DayDate = DateTime.ParseExact(Request.Form["LastOpenDate"].ToString(), "dd/MM/yyyy", CultureInfo.InvariantCulture); dayBegin.DayDate = DayDate; //added d // dayBegin.DayDate = Convert.ToDateTime(Request.Form["LastOpenDate"]); dayBegin.DayEndFlag = 0; dayBegin.DayEndStage = 1; dayBegin.DayReopenFlag = 0; OperationStatus status2 = _idDB0010044Repository.AddAndSave(dayBegin); if (status2 != null && !status2.Status) ModelState.AddModelError("Updation failed", status2.ExceptionMessage); else { CreateInwardSessionsForBranch(BranchId); CreateOutwardSessionsForBranch(BranchId); } } 

这是错误 这个错误我得到了

会是什么问题? 为什么我得到Session null。 什么是解决它的方法

每个线程设置HttpContext.Current 。 因此,当您使用Parallel.ForEach启动更multithreading时,您的新线程无法以这种方式访问​​它。 解决方案是将所需的值作为参数传递,而不是依赖于存储库中的HttpContext.Current

SO上有几个来源已经涵盖了这个问题。

“HttpContext.Current”属性和相关事物的跨线程用法

HttpContext.Current.Items在不同的线程中

从不同的线程访问HttpContext.Current

HttpContext.Current为null,因为它在“非Web线程”中运行。 如果你使用新的Thread(…)分叉一些代码,它将完全相同。 TPL在某种程度上隐藏了这一点,但您仍然需要意识到Parallel.ForEach中的每次迭代都可能在不同的线程中运行,并相应地对其进行处理。

特别是,如果你想在Web请求中使用某些类或方法(并且Parallel.ForEach就是这种用法),你就是不能使用HttpContext.Current。 解决方法是在构造函数中显式传递HttpContext(或HttpContextBase以提高可测试性)(或作为方法参数)

例子:

 var context = HttpContext.Current; Parallel.ForEach(items, item => { DoSomething(context); } ); private static void DoSomething(HttpContext context) { } 

您收到错误是因为您试图从未运行的线程获取HttpContext以响应请求。

HttpContext.Current属性使用该线程来标识要获取的上下文,因为Web服务器可以运行多个线程来处理请求。 当Parallel.ForEach启动新线程时,它们将不会连接到HttpContext

您需要在调用方法时传递方法所需的信息。

进一步加入Bayu Alvian的回答。 我有一个类似的问题,我通过传递上下文作为参数,但在我得到的方法内解决了它

无法使用实例引用访问成员’方法名称’

我通过从上面的答案做一点调整解决了这个问题。

 // Get the new context HttpContext context = HttpContext.Current; Parallel.ForEach(items, item => { DoSomething(context); } ); private static void DoSomething(HttpContext context) { HttpContext.Current = context; } 

将上下文分配给HttpContext.Current会将其删除。