1

In ASP.NET CORE 2.0 I have this behavior: I send two AJAX requests from the browser, the first request to one action (action1 this is an async action) and the second request to other action (action2). While the server is processing the first request, the second request is queued, then when the first request hits the "await" instruction into the action 1, immediately the action 2 start processing the second request and the first request become queued. And this is the expected behavior, but then If I try this in ASP.NET 4.6 I have this behavior: When the first request hits the "await" instruction, the second request keep queued and have to wait until the first action finish the entire processing, for the second action to receive the second request.

This is my server side code

  [HttpPost]
    public async Task<JsonResult> LongRunningAction(HttpPostedFileBase file)
    {
        for (int i = 0; i < 100; i++)
        {                
            await Task.Delay(300);
        }
        return Json("finish");
    }

    [HttpPost]
    public ActionResult ParallelAction()
    {
        return this.Content("result");
    }

This Is my js:

startParallelRequest();
startLongRunningRequest()

function startLongRunningRequest(){
    $.ajax(
        {
            url: "/mycontroller/LongRunningAction",
            data: null,
            processData: false,
            contentType: false,
            type: "POST",
            success: function () {
                stopParallelAction();
            }
        }
    )
} 

var intervalId;

function startParallelRequest() {
    intervalId = setInterval(
        function () {
            $.ajax(
                {
                    url: "/mycontroller/ParallelAction",
                    data: null,
                    processData: false,
                    contentType: false,
                    type: "POST",
                    success: function () {
                    }
                }
            );
        },
        1000
    );
}

function stopParallelRequest() {
    clearInterval(intervalId);
}

What i want to get is a response from the parallel action in each iteration of the loop. This behavior works fine in an ASP.NET 2.0 project but not in ASP.NET 4.6. Thanks In advance.

  • You should *not* code long running requests in your application. Web Servers aren't meant to handle long running requests. They take a request, they should send back a response within a second or two. If it takes longer, then you need to change your process to asynchronous and do the long running task in a background program, such as a Windows Service or an Azure equivalent. – mason Apr 13 '18 at 17:10
  • Hi @manson, thanks for your rapid response, I am not sure to fully understand you, this is an Async Action – Jose Emilio Cabana Apr 13 '18 at 17:19
  • You are confusing asynchronous the concept with `async` the language feature. Though you are using `async` code, your entire process is synchornous. Your browser makes a request and has to wait for a long running process to finish before receiving a response. That's called synchronous. The proper way to handle long running tasks in web applications is to have the browser make a request to the web server to do some long running task, the web server will queue the work to be done elsewhere, and the web server will return a response. Then the browser receives that response. – mason Apr 13 '18 at 17:30
  • At that point, the browser will tell the user the process has been initiated. Then you can have them manually refresh the page to see if anything changes. Or to be more sophisticated you can poll the server to check the status of the long running process (send a request every few seconds, receive a response describing the status). Or even more sophisticated, have the long running process notify the web server (perhaps via SignalR) which then pushes a notification to the browser. – mason Apr 13 '18 at 17:31

1 Answers1

4

The await and async keywords do behave the same. But the behavior of these keywords depends on the SynchronizationContext. And the difference is: ASP.NET Core has no synchronization context.

In all cases, await returns control to the caller and posts a "continuation" (sort of a delegate pointing at the the portion of code after await) to the SynchronizationContext.Current. In ASP.NET (framework), this means the continuations will be picked up one at time, never in parallel; in .NET Core, they can execute in parallel.

This means certain behaviors will be different. For example, in .NET framework, you can easily deadlock yourself, but many of the same things won't deadlock in ASP.NET core because there is no contention for the main "thread" (in reality, the thread can switch due to threading agility, but essentially it's single-threaded). On the other hand, code that is "thread safe" in .NET framework might cause concurrency issues in .NET core. The SynchronizationContext, by the way, is also different in Console and WinForms apps.

It is really really important to understand the SynchronizationContext when using async and await, and it's going to depend on how and where the code is going to run.

See also this question.

John Wu
  • 50,556
  • 8
  • 44
  • 80