2

Posting this question after trying a lot. Doing normal for is not an option because we need to do a large amount of processing in very less time.

I have GetDataFor() inside which HttpContext.Current is used.

The code looks like this:

public void SomeMethod()
{
    var context = HttpContext.Current;

    Parallel.For(0, 100, i =>
    {
        var data = GetDataFor(i, context);
    });
}

public data GetDataFor(int i, HttpContext context)
{
    Uri requestUri = null;
    if (HttpContext.Current != null)
    {
        requestUri = HttpContext.Current.Request.Url;
        sCookie = string.Format("{0}", HttpContext.Current.Request.Headers["cookie"]);
    }
    else
    {
        requestUri = context.Request.Url;
    }

    //do something
    return data;
}

Everything works fine inside normal for loop. However, when I call it inside Parallel.For and pass HttpContext.Current, HttpContext.Current.Request, HttpContext.Current.Request.Url as method parameters:

HttpContext.Current cannot be serialized because it does not have a parameterless constructor

Passing HttpContextBase httpContext = null as parameter throws:

To be XML serializable, types which inherit from ICollection must have an implementation of Add(System.Object) at all levels of their inheritance hierarchy. System.Web.HttpApplicationStateBase does not implement Add(System.Object).

Tried making a property:

public string[] httpContextData
{
    get
    {
        string requestUrl = HttpContext.Current.Request.Url.ToString();
        string sCookie = string.Format("{0}", HttpContext.Current.Request.Headers["cookie"]);
        return new string[] { requestUrl, sCookie };
    }
}

and using in method:

var contextData = httpContextData;

which throws:

System.Uri cannot be serialized because it does not have a parameterless constructor

I did all this to send it's reference and state but unable to understand why the problem is not solving.

How do I use HttpContext.Current inside Parallel.For? What am I doing wrong here?

Btw, the needed stuff are:

HttpContext.Current.Request.Url and HttpContext.Current.Request.Headers["cookie"]

Community
  • 1
  • 1
Zameer Ansari
  • 28,977
  • 24
  • 140
  • 219
  • 1
    Is there anyway you can show your actual code? You've done a good job of explaining what you are doing, but I feel like there must be some key detail your accidentally leaving out. The error you are receiving just doesn't make sense to me given your explanation. – Mark Rucker Feb 18 '16 at 15:58
  • @MarkRucker Sure I also feel that adding code will help future readers (**myself** included). I hope my recent [update](http://stackoverflow.com/posts/35483658/revisions) is [mcve](stackoverflow.com/help/mcve) – Zameer Ansari Feb 18 '16 at 16:40

2 Answers2

3

HttpContext.Current is only available (not null) inside request-handling threads. Parallel.For creates multiple threads, none of which is has access to HttpContext.Current.

You have to pass all data that code in Parallel.For threads needs either through

  • local variables assigned before the loop or
  • TLocal instance used in Parallel.For<TLocal>.

In any event, code such as HttpContext.Current.... is out.

Igor
  • 15,833
  • 1
  • 27
  • 32
  • So, I shall pass `HttpContext.Current.Request.Url` and `HttpContext.Current.Request.Headers["cookie"]` as params? I have tried them :( I'll try [`TLocal`](https://www.google.com/search?q=TLocal) and get back – Zameer Ansari Feb 18 '16 at 14:33
  • I declared `string requestUrl = HttpContext.Current.Request.Url.ToString();` and `string sCookie = string.Format("{0}", HttpContext.Current.Request.Headers["cookie"]);` and passing them as normal string *and not complex serial objects* did the trick. Thanks! – Zameer Ansari Feb 18 '16 at 15:12
0

The code is proprietary hence I'm only posting the relevant parts:

Since passing the following objects:

  • HttpContext.Current

  • HttpContext.Current.Request

  • HttpContext.Current.Request.Url

    as params to GetDataFor was throwing so many errors.

Also, my needs were only

  1. request url which can be re-generated by passing url as string to it's constructor
  2. and a request header's value which is essentially a string

I only passed string to GetDataFor() method:

public void SomeMethod()
{
    string requestUrl = HttpContext.Current.Request.Url.ToString();
    string sCookie = string.Format("{0}", HttpContext.Current.Request.Headers["cookie"]);

    Parallel.For(0, 100, i =>
    {
        var data = GetDataFor(i,
    requestUrl: requestUrl,
    sCookie: sCookie);
    });
}

public data GetDataFor(int i, string requestUrl = null, string sCookie = null)
{
    Uri requestUri = null;
    if (HttpContext.Current != null)
    {
        requestUri = HttpContext.Current.Request.Url;
        sCookie = string.Format("{0}", HttpContext.Current.Request.Headers["cookie"]);
    }
    else
    {
        requestUri = new Uri(requestUrl);
    }

    //do something
    return data;
}
Community
  • 1
  • 1
Zameer Ansari
  • 28,977
  • 24
  • 140
  • 219