Costa
Costa

Reputation: 4085

Confusion about Worker Process threading

Try open the following page in two different tabs in your browser. hit the refresh button to avoid getting the page from browser cache :

    protected void Page_Load(object sender, EventArgs e)
    {
        Thread.Sleep(10000);
        Response.Write(DateTime.Now.ToString());
    }

As you can see, it seems that there is a thread created for every request, and they did not wait for each other there is no lock acquired.

Now Create the following pages, and GlobalCustomClass

GlobalCustomClass

public class GlobalCustomClass
    {
        public static string GlobalVariable
        {
            get;
            set;
        }
    }

Default.aspx

protected void Page_Load(object sender, EventArgs e)
        {
            GlobalCustomClass.GlobalVariable = "Default page";
            Thread.Sleep(10000);
            Response.Write(DateTime.Now.ToString());
            Response.Write("<br />");
            Response.Write(GlobalCustomClass.GlobalVariable);
        }

Page2.aspx

 protected void Page_Load(object sender, EventArgs e)
        {
            Response.Write(DateTime.Now.ToString());
            Response.Write("<br />");
            GlobalCustomClass.GlobalVariable = "Page2";
            Response.Write(GlobalCustomClass.GlobalVariable);

        }

Refresh Default page, and before 10 secs elapses, refresh Page2....Default.aspx is rendering "Page2". Yes it is not thread safe.

Now try this, open the following page in two browser tabs:

    protected void Page_Load(object sender, EventArgs e)
    {
         Session["x"] = "ABC";
         Thread.Sleep(10000);
         Response.Write(DateTime.Now.ToString());
    }

Now it seems that first thread lock on the session object, and the other have to wait for the whole 10 secs!!

Now try First case but put Global.ascx in the project...and say what, first thread locks on something!!!!!

In real application, it is common to access global state variables that need a thread safety like Sessions.

If you have a Backend application that contains a report that need 30 secs to render. and if 60 users opens that report, then user number 61 will wait for half hour till page load into his browser!! That is a Typical thread starvation!! and I will be probably fired :(

1) Every user is waiting till another finish his request. that should make any heavy page a problem. because it can make the whole web application in-responsive. Agree?

2) How to fix that situation?

3) Under which topic I should research about that? Do you know a good book?

Thanks

Upvotes: 0

Views: 1579

Answers (4)

David
David

Reputation: 51

If you need to have concurrent requests from the same user you can

  1. disable session state or
  2. set the session to be ReadOnly in the page directive.

Obviously if the session state is ReadOnly you cannot write to it but you can still read it to figure out who the user is, etc.

Upvotes: 5

Tim M.
Tim M.

Reputation: 54377

Every user is waiting till another finish his request. that should make any heavy page a problem. because it can make the whole web application in-responsive. Agree?

I don't agree. Let's say you have a site with a page that only takes 100ms to execute but supports 1000 concurrent users. By your logic, it would take 100K ms before the last request completed. Obviously that is not the case on high traffic sites.

I doubt there is any lock placed on ViewState (why would there be? it's only relevant to the currently executing page instance).

Session is locked at the beginning of the page lifecycle, but only at the user level which supports my statement that this isn't nearly as big of a problem as you might think. There are also ways around this.

Even back in .NET 1.1 I used to do concurrency testing with the VS tools (Application Center Test) and--while traffic certainly slows a site down--thousands of expensive requests do not create the linear bottleneck you are describing.

I think you would need to create a much more robust test setup to generate conclusive results.

Upvotes: 1

usr
usr

Reputation: 171178

Let's look at the docs:

Concurrent Requests and Session State Access to ASP.NET session state is exclusive per session, which means that if two different users make concurrent requests, access to each separate session is granted concurrently. However, if two concurrent requests are made for the same session (by using the same SessionID value), the first request gets exclusive access to the session information. The second request executes only after the first request is finished. (The second session can also get access if the exclusive lock on the information is freed because the first request exceeds the lock time-out.) If the EnableSessionState value in the @ Page directive is set to ReadOnly, a request for the read-only session information does not result in an exclusive lock on the session data. However, read-only requests for session data might still have to wait for a lock set by a read-write request for session data to clear.

From http://msdn.microsoft.com/en-us/library/ms178581.aspx

So only the same user will be forced to wait. The lock does exist, but only per user.

Upvotes: 2

M4N
M4N

Reputation: 96561

and if 60 users opens that report, then user number 61 will wait for half hour till page load into his browser!!

That's not true, because the lock is only per-session but not global for all users/sessions.

Since you were using the same browser to call the two pages, you were also using the same ASP.NET session (because both tabs share the ASP.NET session cookie). If you use two different browsers to simulate two users, you will see that the second user will not be blocked for 20 seconds.

Also, the locking of course only happens if you are using session state. If you want to create a high-performance web app (with lots of simultaneous users, or simultaneous/asynchronous requests), then you should try to avoid session state as much as possible.

Upvotes: 3

Related Questions