Brandon Church
Brandon Church

Reputation: 177

Session Variable Causes Controller Actions to Fire One at a Time

I have a controller that is executing actions one at a time, almost like it puts my requests in a queue and then responds to each in turn. So, for example, if I click 2 or 3 buttons that are set up to POST to my controller, the controller will eventually fire all the actions, but not right when I click the button.

After tearing my project apart I realized this strange behaviour is somehow caused by setting a Session variable in my default controller action..

Controller:

[HttpGet]
public ActionResult Index() //Start Page
{
    System.Web.HttpContext.Current.Session["SomeString"] = "SomeValue";
    return View();
}

[HttpPost]
public void Run(string json)
{
    for (int i = 0; i < 1000000; i++)
    {
        for (int j = 0; j < 1000000; j++)
        {

        }
    }
}

The index view just contains two elements:

    <a href="#" class="submit">Run</a>
    <a href="Home/OtherPage">Other Page</a>

And AJAX for the button click:

$(document).ready(function () {
    $(".submit").on('click', function () {
        $.ajax({
            type: 'POST',
            url: 'Run',
            data: "SomeString",
            dataType: "text"
        }); 
    }
}

When I remove the line of code setting my session variable, I can click the run button (which starts the long-running loop), click my "OtherPage" button, and instantly navigate to the "OtherPage" view. If I do set the session variable, run the loop, and then click the "OtherPage" button, my app hangs until the loops finish and then navigates to the "OtherPage" view.

Does anyone have any idea why this is happening?

Upvotes: 1

Views: 210

Answers (1)

Adilson de Almeida Jr
Adilson de Almeida Jr

Reputation: 2755

The short answer for your question is:

HostingEnvironment.QueueBackgroundWorkItem(()=>{//your code})

The long and less dangerous answer is: use some queue system, like RabbitMQ or AWS SQS or MSMQ or whatever. Background tasks on web apps is not the best thing you can do in your life, even if the response (success or failure) is not important for you.

EDIT:

If you are using Session State, you probably would need to disable the session state - or set it readonly - in the controller you want some parallelism. Add the following attribute at the controller you want it:

[SessionState(SessionStateBehavior.Disabled)]
public class FooController...

This page explains why this can be necessary in some cases: http://hogaf.github.io/archive/2014/11/13/why-asp.net-requests-are-processed-sequentially

But, again, this is a very bad practice. You had to deal with with ThreadAbortExceptions and will be subject to a lot of other problems.

Upvotes: 1

Related Questions