February 10, 2014

ASP.NET Session and concurrent access

Problem

In one of my projects I found some a strange at first sight issue related to concurrent Session usages. During one long request the other parallel requests were waiting until the previous one is finished.
This issue occurs when user tries to download file from ashx-handler. Handler requires Session to get some user-related configuration which is stored there.

Overview

I've tried to dig deeper and that what I've found.
By default no concurrent access to the asp.net session state is allowed. Requests with same SessionID will be locked exclusively to prevent potential corruption of its state.

What does it mean:

When you have request1 `in progress` and trying to do request2 - Session object will be locked by request1 and our code in request2 will be waiting for request1 completed.

ASP.NET Session is thread safe and synchronization mechanism is based on System.Threading.ReaderWriterLock.

This means that we can do many reads but only one writing at the same time.
ASP.NET Session object is configured for full (read\write) access, by default.

That's why we need to configure Session object as 'read-only' on long-term pages to have non-blocking access to Session object from other pages.

Be aware that even you don't use Session object explicitly you have this issue too.

How to reproduce

To reproduce this issue let's create 2 asp.net pages.

Default page:
<%@ Page Language="C#" %>

<script runat="server">
  protected void Page_Load(object sender, EventArgs e)
  {
      Response.Write("Hello, SessionId " + Session.SessionID);
  }
</script>

Slow page (contains some long-term execution):
<%@ Page Language="C#" %>

<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
        System.Threading.Thread.Sleep(10000);
        Response.Write("Hello, SessionId " + Session.SessionID);
    }
</script>

web.config
<configuration>
  <system.web>
    <sessionState mode="InProc"/>
  </system.web>
</configuration>
Try to open Slow page and Default page at the same time.
You may think that Default page will be opened immediately, but actually it will happen only after Slow page loading completed.

Resolving

To resolve this issue we can re-configure ASP.NET Session object access.

Session state is configured by using the sessionState element of the system.web configuration section.

You can also configure session state by using the EnableSessionState value in the @ Page directive (more info).

If you need non-blocking access to read from Session:
<%@ Page Language="C#" EnableSessionState="ReadOnly"%>

If you don't need Session:
<%@ Page Language="C#" EnableSessionState="False"%>

5 comments:

Monty Richards said...

Good post. You can also implement the "IReadOnlySessionState" interface if this is in an ASHX handler (I don't think the @Page directive works).

peterson said...

Your information about asp.net frame works is really interesting and innovative. Also I want you to share latest updates about this frameworks. Can you update it in your website? Thanks for sharing
Dot net training

jack wilson said...

The Information which you provided is very much useful for Dot Net Training Learners Thank You for Sharing Valuable Information. I like this blog and this is very informative.


Dot Net Course Chennai

Anonymous said...

This doesn't seem reproducible with VS2012

Mithun Mithun said...

Thanks for your informative articel .its very useful
dot net training in velachery | dot net training in chennai | dot net training and placement in chennai