Reputation: 1571
I know that this action method in the asp.net controller class can handle thousands of concurrent requests using only a few threads even if _httpClient.GetAsync
takes many seconds to return. That's because HttpClient.GetAsync()
(in windows) uses I/O completion ports and no thread is running until GetAsync()
returns.
[HttpGet]
public async Task<object> GetData()
{
var result = await _httpClient.GetAsync("https://stackoverflow.com");
return result.StatusCode;
}
But can we say the same for async database operations? Is EF Core using some thread-less async or a new thread will be created for every await SaveChangesAsync()
call?
[HttpPost]
public async Task<ActionResult<object>> PostTodoItem(TodoItem todoItem)
{
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
return ok;
}
When the database is in some remote machine will it leverage some sockets IOCP so we can use the thread for a smaller interval (only for non-network operations in db)?
If a new thread is used for the whole time of the DB operation then I don't see any scalability improvement because for every request I finish the thread that started the Controler/Action and I just start a new (DB) one.
In Winforms or WPF we have a usability improvement because the UI needs to remain responsive but in Asp.Net Core there is no SynchronizationContext or UI to worry about.
I see async/await is used in more places in asp.net core (i.e. razor await Component.InvokeAsync
) but is it really useful?
Upvotes: 1
Views: 264
Reputation: 456487
But can we say the same for async database operations?
Generally, yes. Both the HTTP client and DB query are I/O-based operations, so they don't require a local thread to just sit there waiting for the response.
Is EF Core using some thread-less async or a new thread will be created for every await SaveChangesAsync() call?
The specific implementation depends on the EF Core DB provider. Most of them are async
these days but there are some notable exceptions like SQLite (and possibly Oracle? I don't remember). The common MSSQL provider is fully async
, i.e., not using a separate thread behind the scenes.
When the database is in some remote machine will it leverage some sockets IOCP so we can use the thread for a smaller interval (only for non-network operations in db)?
DB queries are similar to HTTP in the sense that the client sends the query and then the DB responds with the results. There aren't any "non-network operations" from the client side.
Now, if you're asking about the DB server, then that's an implementation detail and doesn't affect how EF Core (or any other DB client) operates at all.
If a new thread is used for the whole time of the DB operation then I don't see any scalability improvement because for every request I finish the thread that started the Controler/Action and I just start a new (DB) one.
This is the exact reason why Task.Run
is discouraged on ASP.NET.
I see async/await is used in more places in asp.net core (i.e. razor await Component.InvokeAsync) but is it really useful?
Razor is a bit more questionable in my mind, but that's coming from a design perspective rather than an efficiency perspective. Async razor allows the page itself to do things like query a db. I prefer to have the action perform all the async work and pass a view model to the page, which is then rendered synchronously since all the data is already in-memory. But that's just a design preference.
As a final note, async
on the web server helps your web server scale. It doesn't change the scalability of your db server at all. If you only have one db server, then allowing your web server to scale probably won't buy you any scalability overall since your bottleneck is likely your db server. Async db calls benefit primarily from cloud dbs or db clusters. That said, if this is new development, then there's no reason not to make the web server async even if it's not the bottleneck. Further discussion in this article.
Upvotes: 1