-1
async void Main()
{
    var cp=new ConentProxy();
    Console.WriteLine(await cp.GetAsync());
    Console.ReadLine();
}

// Define other methods and classes here
public class HttpsContentProvider : IContentProvider
{
    private static HttpClient hc=new HttpClient();

    //**@No.1**
    public async Task<string> GetAsync() {
        return await hc.GetStringAsync("https://www.stackoverflow.com").ConfigureAwait(false);
    }
}

public class DefaultContentProvider : IContentProvider
{
    //**@No.2**
    public async Task<string> GetAsync()
    {
        return await Task.FromResult("Default").ConfigureAwait(false);
    }
}
public interface IContentProvider
{
    Task<string> GetAsync();
}

public class ConentProxy : IContentProvider
{
    public static int conentType = int.Parse(ConfigurationManager.AppSettings["UseHttps"] ?? "0");

    //**@No.3**
    public async Task<string> GetAsync()
    {
        switch (conentType)
        {
            case 0:return await new HttpsContentProvider().GetAsync();
            default:return await new DefaultContentProvider().GetAsync();
        }
    }
}

In the code above, there are three "async" with a "@No." tag ahead. They are all short methods just one or two lines only.

They can be await without "async" as they return Task or Task<T>.

It could be far more than 2 call layer on the No.1 tag in actual code. So there will be many "async"s cascade.

Should I add an "async" to a short method or not ? As I know, there is cost for async and await;

Especilly the No.3, it's just a proxy method. The real operation method will block is the HttpClient.GetStringAsync at @No.1.

=====================================================

After reading the first answer from @dustinmoris, I found the following code in HttpClient class. It makes me confused that there is no async and no ConfigureAwait(false), which is the same as other methods of HttpClient

public Task<byte[]> ReadAsByteArrayAsync()
{
    this.CheckDisposed();
    TaskCompletionSource<byte[]> tcs = new TaskCompletionSource<byte[]>();
    this.LoadIntoBufferAsync().ContinueWithStandard((Action<Task>) (task =>
    {
        if (HttpUtilities.HandleFaultsAndCancelation<byte[]>(task, tcs))
            return;
        tcs.TrySetResult(this.bufferedContent.ToArray());
    }));
    return tcs.Task;
}
Shamork.Fu
  • 53
  • 7
  • Only use async when the operation will take time, like a HTTP request. Don't determine whether to use async by the length of the method. – Sweeper Apr 27 '17 at 06:26
  • 1
    My rule of thumb is to not *start* writing any method as `async`. At the point at which I *need* to insert an `await`, then I'll add `async`. But in your examples, where your methods just `return await`, I'd say you don't *need* the `await` there (if the method isn't `async`). – Damien_The_Unbeliever Apr 27 '17 at 06:36

1 Answers1

0

Technically there are much better explanations, but for beginners the rule of thumb should be:

Use async when

  1. a library offers you an async option, then generally it is doing something which will hugely benefit from async (HttpClient, StreamReader, etc.)
  2. if because of 1. you had to use async somewhere, then you have to use async all the way up, because every higher level method which calls into your async method is now essentially also async.
  3. if 1. and 2. don't apply, don't turn a method into async otherwise

The length of a method has nothing to do with it, actually the smaller your methods the better, because it is a sign of good coding practices.

The additional cost of async/await, even when it is literally all over your code is normally outweighed by the gains you get when you followed rule 1. and 2.

Now to answer the question if you have to decorate a method with async if you can just return the task directly:

Community
  • 1
  • 1
dustinmoris
  • 3,195
  • 3
  • 25
  • 33