【问题标题】:How do I supress the warning about "This async method lacks 'await' operators and will run synchronously" when the interface I implement is async? [duplicate]当我实现的接口是异步的时,如何抑制有关“此异步方法缺少 'await' 运算符并将同步运行”的警告? [复制]
【发布时间】:2019-11-20 05:57:22
【问题描述】:

我在这个方法中没有任何使用 await 的东西!它要我做什么?

    public DatabaseHealthCheck(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public async Task<HealthCheckResult> CheckHealthAsync <------THIS WANTS ASNYC (HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        using (SqlConnection connection =
           new SqlConnection(_configuration.GetConnectionString("PwdrsConnectionRoot")))
        {
            try
            {
                connection.Open();
            }
            catch (SqlException)
            {
                return HealthCheckResult.Healthy();
            }
        }

        return HealthCheckResult.Healthy();
    }
}

}

【问题讨论】:

  • 您可以添加await Task.Yield(); 或使用await connection.OpenAsync() 代替
  • “这需要 ANYC” - 这是不正确的。没有接口可以要求方法为async。但是,它可能要求返回类型为Task&lt;T&gt;。这就是这里发生的事情。
  • 只需将connection.Open() 替换为await connection.OpenAsync()

标签: c# async-await


【解决方案1】:

理想情况下,您不想删除 async 关键字,而是使用底层 API 的异步对应项,以便您的代码在不受 CPU 限制时可以是非阻塞的。比如mentioned in comments,可以用connection.OpenAsync()代替connection.Open()

public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context,
    CancellationToken cancellationToken)
{
    using (SqlConnection connection =
       new SqlConnection(_configuration.GetConnectionString("PwdrsConnectionRoot")))
    {
        try
        {
            await connection.OpenAsync();
        }
        catch (SqlException)
        {
            return HealthCheckResult.Healthy();
        }
    }

    return HealthCheckResult.Healthy();
}

但是,如果您真的只想删除 async 关键字并不理会您的实现,那么您需要使用 Task 显式包装返回值和异常:

private HealthCheckResult CheckHealthImpl(HealthCheckContext context,
    CancellationToken cancellationToken)
{
    using (SqlConnection connection =
       new SqlConnection(_configuration.GetConnectionString("PwdrsConnectionRoot")))
    {
        try
        {
            connection.Open();
        }
        catch (SqlException)
        {
            return HealthCheckResult.Healthy();
        }
    }

    return HealthCheckResult.Healthy();
}

public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context,
    CancellationToken cancellationToken = default)
{
    try
    {
        return Task.FromResult(CheckHealthImpl(context, cancellationToken));
    }
    catch (Exception e)
    {
        return Task.FromException(e);
    }
}

这应该正确实现接口,并保留与您之前的 async 函数等效的行为。

【讨论】:

    【解决方案2】:

    如果您需要保持async 的方法,有几种方法可以解决您的问题:

    1. 最简单的方法是使用静态结果返回 await Task.FromResult(HealthCheckResult.Healthy())

    2. 您还可以在 Visual Studio 中抑制特定类型的警告,如 this doc 所示。 TLDR:您可以在项目的属性中更改它。

    如果这有帮助,请告诉我!

    保重。

    【讨论】:

    • async 与实现接口无关。 async 只是异步函数的一个实现细节。合约中必须履行的部分是Task&lt;HealthCheckResult&gt;的返回类型
    • 您应该使用await Task.FromResult 的唯一情况是您的方法的另一部分等待实际异步的东西。否则,您可以删除 async 关键字并返回 Task.FromResult(...) 以节省一些 CPU 周期。
    猜你喜欢
    • 2015-07-07
    • 1970-01-01
    • 2017-04-30
    • 2019-09-25
    • 1970-01-01
    • 2019-08-27
    • 1970-01-01
    • 2014-02-13
    • 1970-01-01
    相关资源
    最近更新 更多