2014-11-03 79 views
6

此方法 - doDayBegin(item.BranchId)需要很长时间才能执行。所以我使用Parallel.ForEach并行执行它。当我使用正常foreach循环其工作正常,但是当我使用Parallel.ForEach它显示此错误
对象引用未设置为对象的实例。Parallel.ForEach错误HttpContext.Current

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 error i am getting

会是怎样的问题?为什么我得到会议空。什么办法解决它

回答

19

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

在这里有几个来源已经涵盖了这个问题。

The cross-thread usage of "HttpContext.Current" property and related things

HttpContext.Current.Items in different thread

Access HttpContext.Current from different threads

1

,因为你正试图从没有对响应请求的目的,运行的线程得到HttpContext你得到的错误。

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

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

2

HttpContext.Current为空,因为它在“非Web线程”中运行。如果你使用新的线程(...)分配了一些代码,它将完全相同。 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) { 
} 
0

进一步增加鲅鱼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将其删除。