2

Hello I have this code on my controller:

[HttpGet]
[Route("/Test")]
public async Task<IActionResult> Test() {
    Console.WriteLine("foo");
    await Task.Delay(2000);
    Console.WriteLine("bar");
    return Ok();
}

And try to test by javascript:

for(let i=0; i<2; i++){
    axios.get('/Test').then(response => {
        console.log(`task ${i} finish`)
    })  
}

I expect the output on server should be:

foo
foo
foo
bar
bar
bar

However what I got is:

foo
bar
foo
bar
foo
bar

I get confused that didn't await Task.Delay(2000) will return the control flow back to process and able to handle other request meanwhile? It seems to me that the action method is not capable to handle large number of requests concurrently. Am I misunderstand something about async/await? What should I implement if I want to simulate a non-blocking lengthy web service call?

I read this post but still can't figure out what is the solution

MasterWil
  • 891
  • 8
  • 24

2 Answers2

1

Most likely ASP.NET processes requests from same client in order. Means it will not start processing second request while first is in progress. It was true for older ASP.NET MVC on full framework and it was done like that to avoid concurrent access to session state. It was possible to change this behavior by applying SessionState(SessionStateBehaviour.Disabled) attribute. Check this question ASP.NET MVC and Ajax, concurrent requests?. Maybe something similar applies to ASP.NET Core.

Am I misunderstand something about async/await? What should I implement if I want to simulate a non-blocking lengthy web service call?

Request processing is not blocking. They are simply sequential. If you try to access same action from different clients (browsers) you will see that they execute in parallel.

Andrii Litvinov
  • 12,402
  • 3
  • 52
  • 59
  • 1
    Thank you. After I created some duplicated methods on ASP.NET Core side and fire multiple requests from different browsers, I started to see they return simultaneously. It's a bit weird to me that ASP.NET Core treat requests from different tabs as the same source, executing the action method one by one. It turns out I have to use 2 different browsers to see the expected result. – MasterWil Dec 20 '17 at 04:02
0

I never really worked with axios before but from the look of the code, your ASP.NET code isn't the problem, it's the javascript.

ASP.NET handles async/await very well, and in your example it's doing the right thing. The problem is that it looks like your javascript does 1 request at a time, waits for the result (which takes 2 seconds) then continues the for loop.

for(let i=0; i<2; i++){
    // this starts a request to /Test and waits the result
    // since your controller waits 2 seconds before returning OK
    // it looks like its sync
    axios.get('/Test').then(response => {
        console.log(`task ${i} finish`)
    })  
}

Isn't there a callback-based function to do your tests?

Haytam
  • 4,643
  • 2
  • 20
  • 43
  • I suppose `axios.get()` will return a Promise immediately and continue executing the for-loop and eventually all 3 calls will return almost at the same time instead of synchronous/sequential way. – MasterWil Dec 19 '17 at 08:27
  • 1
    @OptimusFrog you can check what requests are being sent to server in browser's developer tools. You will then know for sure if the problem is on client or server side. – Andrii Litvinov Dec 19 '17 at 08:51