【发布时间】:2017-04-27 06:21:20
【问题描述】:
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();
}
}
}
在上面的代码中,前面有三个带有“@No.”标签的“async”。它们都是简短的方法,只有一两行。
它们可以在没有“异步”的情况下等待,因为它们返回 Task 或 Task<T>。
实际代码中No.1标签上的调用层可能远不止2个。所以会有很多“异步”级联。
我应该在短方法中添加“异步”吗?据我所知,async 和 await 需要付费;
特别是No.3,它只是一种代理方法。真正的操作方法会阻塞在@No.1处的HttpClient.GetStringAsync。
================================================ ======
在阅读@dustinmoris 的第一个答案后,我在HttpClient 类中找到了以下代码。让我困惑的是没有async也没有ConfigureAwait(false),这和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;
}
【问题讨论】:
-
仅当操作需要时间时才使用异步,例如 HTTP 请求。不要通过方法的长度来决定是否使用异步。
-
我的经验法则是不要开始将任何方法写成
async。在我需要插入await时,我将添加async。但是在你的例子中,你的方法只是return await,我想说你不需要那里的await(如果方法不是async)。
标签: c# .net asynchronous async-await