首页 > 解决方案 > 消除异步和等待流程

问题描述

在关于省略 async await的文章中,有一个例子如下:

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

他将流程描述如下:

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

  1. 创建 HttpClient 对象。

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

  3. 释放 HttpClient 对象。

  4. 返回从 GetStringAsync 返回的任务。

为什么流程不如下?

  1. 创建 HttpClient 对象。

  2. 释放 HttpClient 对象。

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

标签: c#async-await

解决方案


没有花括号或分号的 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);
}

推荐阅读