I have an ASP.NET API which exposes some DB operations. DB API itself is synchronous and can't be changed. I'm aware that using Task.Run in ASP.NET is a bad idea and I was going to make the web API sync but started to think about different possible ways about making DB operations async and wonder if any of these is a good idea.
- Use
Task.FromResult
[HttpGet]
public async Task<Result> Get()
{
return Task.FromResult(DBOperation());
}
This feels like it'd only be good just to allocate Task
in addition to result.
- Use
ValueTask
return new ValueTask<Result>(DBOperation());
Feels same as Task (just allocate more)? Not sure if ValueTask being struct would be better or worse.
- Use
TaskCompletionSource
public Task<Result> DBOperation()
{
TaskCompletionSource<Result> tcs = new TaskCompletionSource<Result>();
//db call
tcs.SetResult(<result>);
return tcs.Task;
}
Not sure if it'd help.
- Use
Task.Yield
public Task<Result> DBOperation()
{
await Task.Yield();
//db call
}
Maybe?
What do you think?
CodePudding user response:
wonder if any of these is a good idea.
Nope.
Every attempt at async-over-sync on ASP.NET causes additional memory overhead. And some of them (Task.Run
and Task.Yield
) also cause an additional thread switch.
The whole point of asynchronous code is to free up a thread, but if you have an unavoidable blocking call, then the thread can't be freed, by definition. As Panagiotis pointed out, you might be able to replace the blocking call with an asynchronous one, but if not, then async-over-sync won't help you.