2014-11-03 66 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將其刪除。