0

I'm a bit confused on best practices with c# and tasks.
When I was taught c# and tasks it was always an async function that awaits a task. But recently I have been doing some research and found some people who say otherwise. They also say that limiting usage of async and await can improve performance and Ram usage.

For example in This Stackoverflow post It says you shouldn't always await every task but the example isnt for an ASP.NET API and there isn't any previous data used to get the new data. This post also is in favor of not always awaiting every task. But again the example is a simple task being passed through.

So my question is for cases when there is another task on which the second task must wait. Can you use .Result or is it better us use async/await. Because I heard .Result is blocking the current thread. But I can't see how the current thread would not be blocked by the await since the output of the first statement is needed for the second statement.

Example without async/await

public Task<User> SaveUser(User user) 
{
    var dbUser = _userRepository.GetByUid(user.Id).Result;
    if(dbUser == null) {
        dbUser = new User();
        dbUser.Id = Guid.NewGuid();
    }
    dbUser.Name = user.Name;

    return _userRepository.Save(dbUser);

}

Example with async/await

public async Task<User> SaveUser(User user) 
{
    var dbUser = await _userRepository.GetByUid(user.Id);
    if(dbUser == null) {
        dbUser = new User();
        dbUser.Id = Guid.NewGuid();
    }
    dbUser.Name = user.Name;

    return await _userRepository.Save(dbUser);

}

Note: I also heard that when using an UI, it's important that UI related tasks are awaited but this would be for API's.

Torbjörn Hansson
  • 18,354
  • 5
  • 33
  • 42
lieven121
  • 41
  • 5
  • 2
    You misunderstood what you read. The post doesn't say you should use `.Result`. It says you don't need `await` if you're only going to return a Task without using its result in your method. That's not the case here, so you should always use `await` – Panagiotis Kanavos Apr 22 '21 at 08:22
  • 1
    `But again the example is a simple task being passed through.` exactly. That's the only case where you can omit `await`. `async/await` don't make a method asynchronous. `async` is just syntactic sugar that allows the use of `await` to await an already asynchronous method to complete without blocking. – Panagiotis Kanavos Apr 22 '21 at 08:25
  • 1
    `this would be for API's.` it's even more important here - instead of blocking a single user, you could end up freezing an entire server, or delaying every request on a site. Each request is served by a separate thread coming from a thread pool. The same number of threads (and cores) can be used to serve far more requests on the same iron when blocking is avoided – Panagiotis Kanavos Apr 22 '21 at 08:27

1 Answers1

6

I recommend reading my async intro and following up with my post on eliding async and await. TL;DR: use async/await by default, and only elide them when the method is a simple passthrough method. Since your example is not a simple passthrough method, you should keep the async/await keywords.

It's also important to draw a distinction between "asynchronous" and async. There are several kinds of asynchronous code, whereas async is an implementation detail - one specific kind of asynchronous code. Both of the methods in your question are asynchronous, but only one uses async.

They also say that limiting usage of async and await can improve performance and Ram usage.

Yes, by removing the state machine overhead of the async keyword. However, this also removes all the benefits of the state machine, so you should only remove async on simple passthrough methods.

Can you use .Result or is it better us use async/await. Because I heard .Result is blocking the current thread.

You should use async/await whenever possible, and avoid Result, even on ASP.NET Core.

But I can't see how the current thread would not be blocked by the await since the output of the first statement is needed for the second statement.

The thread is not blocked. await works by sticking a bookmark in the method and then returning a result. So the thread is not blocked, but you can think of the method as "paused". https://blog.stephencleary.com/2012/02/async-and-await.html

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810