简体   繁体   English

Parallel.ForEach错误HttpContext.Current

[英]Parallel.ForEach error HttpContext.Current

this method - doDayBegin(item.BranchId) is taking long time to execute. 这个方法 - doDayBegin(item.BranchId)需要很长时间才能执行。 So I am using Parallel.ForEach to execute it parallel. 所以我使用Parallel.ForEach执行它。 When I am using normal foreach loop its working fine but when i am using Parallel.ForEach it showing this error 当我使用正常的foreach循环时它的工作正常,但当我使用Parallel.ForEach它显示此错误
Object reference not set to an instance of an 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 error 这是错误 这个错误我得到了

what will be the issue? 会是什么问题? why i am getting Session null. 为什么我得到Session null。 what is way to solve it 什么是解决它的方法

HttpContext.Current is set per thread. 每个线程设置HttpContext.Current So when you fire up more threads using Parallel.ForEach your new threads can't access it that way. 因此,当您使用Parallel.ForEach启动更多线程时,您的新线程无法以这种方式访问​​它。 The solution would be to pass the needed values as parameters all the way instead of relying on HttpContext.Current in your repositories. 解决方案是将所需的值作为参数传递,而不是依赖于存储库中的HttpContext.Current

There are several sources here on SO that covers this problem already. SO上有几个来源已经涵盖了这个问题。

The cross-thread usage of "HttpContext.Current" property and related things “HttpContext.Current”属性和相关内容的跨线程用法

HttpContext.Current.Items in different thread HttpContext.Current.Items在不同的线程中

Access HttpContext.Current from different threads 从不同的线程访问HttpContext.Current

You get the error because you are trying to get the HttpContext from a thread that is not running for the purpose of responding to a request. 您收到错误是因为您尝试从未运行的线程获取HttpContext以响应请求。

The HttpContext.Current property uses the thread to identify which context to get, as the web server can run several threads to handle requests. HttpContext.Current属性使用该线程来标识要获取的上下文,因为Web服务器可以运行多个线程来处理请求。 As the Parallel.ForEach starts new threads, they will not be connected to a HttpContext . Parallel.ForEach启动新线程时,它们将不会连接到HttpContext

You need to pass along the information that the method needs in the call to the method. 您需要在调用方法时传递方法所需的信息。

HttpContext.Current is null because it's running in "non-web threads". HttpContext.Current为null,因为它在“非Web线程”中运行。 If you forked some code using new Thread(...) it would be exactly the same. 如果你使用新的Thread(...)分叉一些代码,它将完全相同。 The TPL somewhat hides this, but you still need to realize that each iteration in your Parallel.ForEach can potentially run in a different thread, and treat it accordingly. TPL在某种程度上隐藏了这一点,但您仍然需要意识到Parallel.ForEach中的每次迭代都可能在不同的线程中运行,并相应地对其进行处理。

In particular, if you want to use some class or method out of the web request (and Parallel.ForEach is such an usage) you just can't use HttpContext.Current. 特别是,如果你想在web请求中使用某些类或方法(并且Parallel.ForEach就是这种用法),你就是不能使用HttpContext.Current。 A workaround is to explicitly pass the HttpContext (or HttpContextBase for improved testability) in the constructor (or as a method parameter) 解决方法是在构造函数中显式传递HttpContext(或HttpContextBase以提高可测试性)(或作为方法参数)

example : 例如:

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



private static void DoSomething(HttpContext context) {
}

Further adding to Bayu Alvian answer. 进一步加入Bayu Alvian的回答。 I had a similar problem and I solved it by passing the context as parameter but inside the method I got 我有一个类似的问题,我通过传递上下文作为参数,但在我得到的方法内解决了它

Member 'method name' cannot be accessed with an instance reference 无法使用实例引用访问成员'方法名称'

I solved it by doing a little tweak from the above answer. 我通过从上面的答案做一点调整解决了这个问题。

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

private static void DoSomething(HttpContext context) {
 HttpContext.Current = context;
}

Assigning the context to the HttpContext.Current removes it. 将上下文分配给HttpContext.Current会将其删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM