I have come across a small issue. I have written a asp.net web api service and I automatically added "async" on the controller, of course this now requires that I use await.
The problem I have is that my controller is connected to a service layer and this service layer then connects to a data layer - this data layer is the layer that is calling an ASYNC version of GET to make an asynchronous call to another REST service - so this is easy, I can convert my data layer method to have an "async" keyword and i will place a await on the HttpClient GetSync call.
But my service layer to support async / await I need to change the return type to Task<T>
but the service layer really isn't doing anything async, it's calling to the data layer that is actually calling HttpClient async methods.
So I have two options considering I have the following layer structure.
ASP.NET Web Api >> Service Layer >> Data Layer
Only have async and await used in the Data Layer and be done with it.
Or place async and await on the controller and the method from the service layer, this requires refactoring as I need to return Task<T>
.
I suppose where I am not understanding it fully, technically the only blocking calls would be in the data layer, so to have all threads returned the thread pool for use I should only be concerned with placing async and await on the data layer?
When would I need to use pattern on the controllers?
I automatically added "async" on the controller, of course this now requires that I use await.
That is backwards. You should only add async
to a method if you need to use await
.
Only have async and await used in the Data Layer and be done with it.
You shouldn't wrap asynchronous methods within synchronous APIs. This is especially true in server code, because then you lose all the benefits of async
.
Or place async and await on the controller and the method from the service layer, this requires refactoring as I need to return Task.
This is the correct approach. Follow these guidelines:
async
code. E.g., do not call Task.Wait
or Task<T>.Result
. I describe on my blog how this can cause deadlocks, but even if you hack it to work reliably, you'll still lose all the benefits of async
on the server side.async void
. Especially on the server side.Wait
or Result
, use await
. This means that the awaiting method will have to be async Task
or async Task<T>
, which means that methods that call the awaiting method will also have to await. So async
will "grow" through your code. This is normal and correct.You may find my article on Best Practices in Asynchronous Programming helpful.