Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have a issue here. In my web app i have a page that starts another thread for time consuming task. In this new thread i have a call to one of my architecture methods (Inside another project - an architecture project). The problem is: in one of this methods i access a HttpContext.Current.Session field. But when i launch the application a exception is thrown saying that this object (HttpContext.Current.Session) has a null reference. How could i set the context of the new thread the same as HttpApplication context in order to access HttpContext.Current.Session ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
184 views
Welcome To Ask or Share your Answers For Others

1 Answer

There's a number of things to consider here.

If your thread has a lifetime equal to that of the page and you need a good deal of random access to the HttpSessionState, then you should get the SynchronizationContext from the call that creates the background thread using the static Current property.

Once you have that, you can pass that to your thread and then when you need access to anything on the HttpContextBase associated with the request (and this includes the session), you can call the Post method on the SynchronizationContext that you passed to your thread to get values (or set them):

// From thread servicing request.
var sc = SynchronizationContext.Current;

// Run the task
Task t = Task.Run(() => {
    // Do other stuff.
    // ...

    // The value to get from the session.
    string sessionValue = null;

    // Need to get something from the session?
    sc.Post(() => {
        // Get the value.
        sessionValue = HttpContext.Current.Session["sessionValue"];
    }

    // Do other stuff.
    // ...
});

It's important to do this, as access to the HttpContextBase (and anything associated with it) is not thread-safe and is tied to the thread (well, the context) processing the request.

Note that the Post method doesn't block, so code that comes after the call to Post (i.e. the lines after // Do other stuff.) should be independent of the delegate that's passed to Post. If the code that comes after is dependent and you need to wait for the call to complete before continuing, then you can call the Send method; it has the same signature and will block until the code in the delegate is executed.

That said, if you want just read-only access to the values, then it's better to get them before you call your code, and then access them in your background thread:

// Get the values needed in the background thread here.
var values = {
    SessionValue = HttpContext.Current.Session["sessionValue"];
};

// Run the task
Task t = Task.Run(() => {
    // Do other stuff.
    // ...

    // Work with the session value.
    if (values.SessionValue == ...)

    // Do other stuff.
    // ...
});

If your thread is going to continue to process after the request is serviced, then you only have read-only state, and you have to capture it before you start the thread. Once the request is serviced, even though the session lives, it's a logical concept; depending on the provider for the session state (session state manager, SQL Server, etc.), the object could be hydrated every time a new request comes in.

You'd also have to deal with session timeout issues, you wouldn't know if the session even exists at the point you want to access it.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...