4

We have recently developed an ASP.Net WebAPI2 that is using the synchronous calls across various layers as below.

enter image description here

Now I have learnt that it's best to use the Async Task approach for stability reasons but as the code is already developed for most of the functionality using sync calls, I was wondering what is the best way to convert the calls I have.

Say this is how my code is initially written:

[Route("user/{userId}/feeds ")]
[HttpGet]
public IEnumerable<NewsFeedItem> GetNewsFeedItemsForUserAsync(string userId)
{
    return newsFeedService.GetNewsFeedItemsForUser(userId);
}

I can convert this to something like this:

[Route("user/{userId}/feeds ")]
[HttpGet]
public async Task<IEnumerable<NewsFeedItem>> GetNewsFeedItemsForUserAsync(string userId)
{
    return await Task.Run(()=>newsFeedService.GetNewsFeedItemsForUser(userId));
}

But, if I understand correctly, I don't think that will help me scale up my website as it will still end up using the thread pool thread.

The only other option I see to modify all the layers and all the functions to use async but that seems like a lot of work.

So I was wondering if anyone here had to undergo a similar exercise and what is the best way to address the problem.

Regards Kiran

Paul
  • 1,435
  • 14
  • 32
Kiran
  • 2,754
  • 5
  • 26
  • 61
  • `async` all the way... – Patrick Hofman Nov 04 '15 at 11:50
  • The best way would be that `newsFeedService` offers an `async` method, so you can just `await` it from the controller. Meanwhile, `newsFeedService` should have an `async` DAO / Repository, which should have `async` persistence strategies, which should have `async` methods, which should communicate asynchronously to the underlying database... (The point is that you will have to convert all the execution flow to `async`) – Matias Cicero Nov 04 '15 at 11:51
  • Also if `await` is the last statement of the method, you can remove it. After removing it, if you're left with no `await` statements, you can drop the `async` keyword too. – Sriram Sakthivel Nov 04 '15 at 11:56
  • I will link to my standard posts about whether to use async or not: http://stackoverflow.com/a/25087273/122718 Why does the EF 6 tutorial use asychronous calls? http://stackoverflow.com/a/12796711/122718 Should we switch to use async I/O by default? You probably will discover that you should not use async because under ASP.NET most usages of async result in no benefit whatsoever. – usr Nov 04 '15 at 21:36
  • @usr: Those were nice discussions, I learnt a lot from those comments. Thanks – Kiran Nov 05 '15 at 03:31

1 Answers1

3

only other option I see to modify all the layers and all the functions to use async but that seams like a lot of work.

You're right, writing up a whole new data access layer that exposes true asynchronous methods is hard work, as it usually needs to be re-written from the ground up. But, if you know you actually need scalability and you've identified it as your current bottleneck, then it will end up being worth it.

Wrapping your code in Task.Run will benefit nothing, as you stated yourself, because what async does exactly is free a thread-pool thread while it does IO, where here you're actually consuming another thread, other than the one that ASP.NET runtime already provided you with.

To conclude, there is no easy magic fix to make this all work, it will require you to re-write/add async endpoints to the calling code.

Yuval Itzchakov
  • 136,303
  • 28
  • 230
  • 296
  • Both ADO.NET and Entity Framework provide asynchronous methods. Changing the data layer may not be so difficult – Panagiotis Kanavos Nov 04 '15 at 16:32
  • @Yuval Itzchakov: Thanks, looks like only way is to do the hard way. how I wish if there was a some way to flag the compiler (say using attributes) to make any I/O call as await in the full call chain :) – Kiran Nov 05 '15 at 03:37