简体   繁体   中英

async Controller with async Action doesn't work

I have async controller with async action. In the action I call WCF service method in SomeMethodOne (it needs 10 seconds to return result) and then I execute some mathematical operations in SomeMethodTwo (it executes about 6 seconds on my computer). As I understand during waiting on result from WCF service method, my computer should execute SomeMethodTwo but it doesn't and all code executes 10 seconds + 6 seconds = 16 seconds. Why?

public class TestController : AsyncController
{
    public async Task<ActionResult> Index()
    {
        string result =  await SomeMethodOne();

        SomeMethodTwo();

        return View();
    }

    private async Task<string> SomeMethodOne() // it needs 10 seconds to return result from WCF service
    {
        using (Service1Client client = new Service1Client())
        {
            return await client.GetDataAsync(5);
        }
    }

    private void SomeMethodTwo() // it executes about 6 seconds on my computer
    {
        double result = 0;
        for (int i = 0; i < 1000000000; i++)
        {
            result += Math.Sqrt(i);
        }
    }
}

The WCF service which I run locally:

public class Service1 : IService1
{
    public string GetData(int value)
    {
        Thread.Sleep(10000);
        return string.Format("You entered: {0}", value);
    }        
}

Your problem is that you're using await right away:

string result =  await SomeMethodOne();

The await means that your controller action is going to "asynchronously wait" (await) for the result of SomeMethodOne before it continues executing.

If you want to do asynchronous concurrency, then don't await right away. Instead, you can start the asynchronous operation going by calling the method and then await later:

public async Task<ActionResult> Index()
{
  Task<string> firstOperation = SomeMethodOne();

  SomeMethodTwo();

  string result = await firstOperation;

  return View();
}

and then I execute [emphasis mine]

Doing one thing and then doing another thing will take as long as both of them added together.

Doing two things at the same time might be quicker. It might be slower, because of context switching (imagine someone doing lots of "multitasking" and spending more time switching between them than working). It's likely it will be quicker here, if you don't have to get the results from the first action in order to do the second:

public async Task<ActionResult> Index()
{
    Task<string> task =  SomeMethodOne();

    SomeMethodTwo();

    string result = await task;

    return View();
}

Obviously if you needed result before you could call SomeMethodTwo() then this wouldn't be possible. There is still an advantage on await ing SomeMethodOne() (which should be called SomeMethodOneAsync() if possible to fit with .NET conventions), in that if GetDataAsync() is truly async then the thread that was executing this action method can do something else for some other request to your web application, and another thread will pick up on dealing with this one when the I/O operation has returned data. This doesn't help the performance of the single method involved, but does help overall scalability of all the methods being run on the machine for all the web requests.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM