避免异步并等待流

时间:2019-09-19 01:46:12

标签: c# async-await

在有关eliding async await的文章中,有一个如下示例:

public Task<string> GetElidingKeywordsAsync(string url)
{
    using (var client = new HttpClient())
        return client.GetStringAsync(url);
}

他对流程的描述如下:

  

使用GetElidingKeywordsAsync,代码可以执行以下操作:

     
      
  1. 创建HttpClient对象。

  2.   
  3. 调用GetStringAsync,它返回一个   任务不完整。

  4.   
  5. 处理HttpClient对象。

  6.   
  7. 返回从GetStringAsync返回的任务。

  8.   

为什么流程不如下?

  1. 创建HttpClient对象。

  2. 处理HttpClient对象。

  3. 调用GetStringAsync,并返回从GetStringAsync返回的任务。

2 个答案:

答案 0 :(得分:4)

没有花括号或分号的using块具有隐含的主体:

public Task<string> GetElidingKeywordsAsync(string url)
{
    using (var client = new HttpClient())
        return client.GetStringAsync(url); // using body
}

这可以归一化为:

public Task<string> GetElidingKeywordsAsync(string url)
{
    using (var client = new HttpClient())
    {
        return client.GetStringAsync(url);
    }
}

或更紧凑地用C#8.0编写:

public Task<string> GetElidingKeywordsAsync(string url)
{
    using var client = new HttpClient();
    return client.GetStringAsync(url);
}

如果添加分号,则将出现一个空的主体,并产生您在OP中描述的行为:

public Task<string> GetElidingKeywordsAsync(string url)
{
    HttpClient client;
    using (client = new HttpClient());  // gets disposed before next statement
        return client.GetStringAsync(url);  // don't be fooled by the indent
}

这可以归一化为:

public Task<string> GetElidingKeywordsAsync(string url)
{
    HttpClient client;
    using (client = new HttpClient())
    {
    }
    return client.GetStringAsync(url);
}

答案 1 :(得分:2)

扩展上面给出的注释,如果您了解GetStringAsync方法的工作原理,将会很有帮助。

假设以下是aysnc方法:

public async Task<string> GetMethodAsync(string url)
{
    // perform some operations

    // execution will pause here due to await statement 
    // after calling download URL and the Task will be returned
    var result = await DownloadURL(string);

    //perform some more function
    // finally return the result
    return result;
}

请注意,此处将执行对DownloadURL的方法调用,然后只有执行暂停以等待结果返回,然后返回task。制作方法Async本身并不能使您延迟执行,而仅在await调用之后的部分得到“延迟”。

这就是为什么您将获得不完整的任务,然后在下一步处理客户的原因。