Parallel.ForEach HttpContext.Current Error

this method - doDayBegin(item.BranchId) takes a lot of time to execute. Therefore, I use Parallel.ForEach to execute it in parallel. When I use a regular foreach , it works fine, but when I use Parallel.ForEach , it shows this error
The reference to the object is not installed in the instance of the object.

  public ActionResult Edit([DataSourceRequest] DataSourceRequest request) { try { JavaScriptSerializer js = new JavaScriptSerializer(); List<DB0010020Vm> _listDB0010020Vm = new List<DB0010020Vm>(); string dataDB0010020vm = Request.Form["griddetailsvm"]; if (!string.IsNullOrEmpty(dataDB0010020vm)) { _listDB0010020Vm = js.Deserialize<List<DB0010020Vm>>(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); } } 


this is mistake this error i am getting

, what is the problem? why am I getting session null. what way to solve it

+6
source share
4 answers

HttpContext.Current is set in the stream. Therefore, when you start more threads using Parallel.ForEach , your new threads cannot access it this way. The solution would be to pass the required values ​​as parameters, rather than relying on HttpContext.Current in your repositories.

There are several sources in SO that are already addressing this issue.

Use of cross-streams "HttpContext.Current" property and related things

HttpContext.Current.Items in another thread

Access to HttpContext.Current from different threads

+19
source

HttpContext.Current is null because it works in non-web streams. If you fork some code using the new Thread (...), it will be exactly the same. TPL hides this somewhat, but you still need to understand that each iteration in Parallel.ForEach can potentially run in another thread and process it accordingly.

In particular, if you want to use any class or method from a web request (and Parallel.ForEach is such a use), you simply cannot use HttpContext.Current. The workaround is to explicitly pass the HttpContext (or HttpContextBase to improve validation) in the constructor (or as a method parameter)

example:

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

You get an error because you are trying to get an HttpContext from a thread that is not running to respond to a request.

The HttpContext.Current property uses a thread to determine which context to get, since the web server can run multiple threads to process requests. When Parallel.ForEach launches new threads, they will not be connected to the HttpContext .

You need to pass the information needed by the method in the method call.

+1
source

Further addition to the answer to Bai Alvian. I had a similar problem, and I solved it by passing the context as a parameter, but inside the method I received

Method name "Member" cannot be accessed using instance link

I solved this by making a little tweak from the answer above.

 // 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 context assignment deletes it.

0
source

Source: https://habr.com/ru/post/977641/


All Articles