这种方法 - doDayBegin(item.BranchId)
需要很长时间才能执行。所以我使用Parallel.ForEach
并行执行它。当我使用普通foreach
循环时,它的工作正常,但当我使用Parallel.ForEach
时,它显示此错误
未将对象引用设置为对象的实例。
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);
}
}
这是错误
会出现什么问题?为什么我得到Session null。什么是解决方法
答案 0 :(得分:19)
HttpContext.Current
。因此,当您使用Parallel.ForEach
启动更多线程时,您的新线程无法以这种方式访问它。解决方案是将所需的值作为参数传递,而不是依赖于存储库中的HttpContext.Current
。
这里有几个来源已经涵盖了这个问题。
The cross-thread usage of "HttpContext.Current" property and related things
答案 1 :(得分:2)
您收到错误是因为您试图从未运行的线程中获取HttpContext
以响应请求。
HttpContext.Current
属性使用线程来标识要获取的上下文,因为Web服务器可以运行多个线程来处理请求。当Parallel.ForEach
启动新主题时,它们将不会连接到HttpContext
。
您需要在调用方法时传递方法所需的信息。
答案 2 :(得分:2)
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) {
}
答案 3 :(得分:1)
进一步加入Bayu Alvian的回答。我有一个类似的问题,我通过传递上下文作为参数,但在我得到的方法
内解决了它会员&#39;方法名称&#39;无法使用实例引用访问
我通过对上述答案进行一些调整解决了这个问题。
// 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会将其删除。