正确的方法来制作异步方法

And*_*ome 4 c# asynchronous

以下是制作异步方法的正确方法,其中方法中的代码必须执行需要等待的多个异步调用.计划是启动此方法的多个,并在代码继续之前等待所有这些方法完成.

    public static Task<string> Get(string url)
    {
        return Task.Run(async () =>
        {
            var client = getBaseHttpClient();
            var result = await client.GetAsync(url).ConfigureAwait(false);
            if (result.IsSuccessStatusCode)
            {
                return await result.Content.ReadAsStringAsync();
            }
            return null;
        });
    }
Run Code Online (Sandbox Code Playgroud)

dca*_*tro 8

你的代码:

  1. 启动一个线程池线程(Task.Run),
  2. 这将启动异步I/O操作(GetAsync),然后返回到线程池.
  3. 当I/O完成(await)时,将启动另一个线程池线程(ConfigureAwait(false)),
  4. 这将启动另一个异步I/O操作来读取HTTP响应(GetAsStringAsync)的内容,然后返回到线程池.
  5. 当I/O完成(await)时,将启动另一个线程池线程将内容返回给调用方法.

你可以完全跳过第1步.它只是将调用推迟到getBaseHttpClient线程池线程,我认为这不是密集的CPU绑定工作 - 在这种情况下,它可以/应该同步完成.

public static async Task<string> Get(string url)
{
    var client = getBaseHttpClient();
    var result = await client.GetAsync(url).ConfigureAwait(false);
    if (result.IsSuccessStatusCode)
    {
        return await result.Content.ReadAsStringAsync();
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)

调用代码将是:

var tasks = urls.Select(Get);
var responses = await Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)