【问题标题】:How to remove StyleCop warning "This async method lacks 'await' operators and will run synchronously" without removing async from signature如何删除 StyleCop 警告“此异步方法缺少 'await' 运算符并将同步运行”而不从签名中删除异步
【发布时间】:2019-02-22 16:47:01
【问题描述】:

父对象和大多数子对象都有异步并使用等待。 StyleCop 正在观看并因缺少一个子班的等待而大发雷霆。

当您无法删除异步签名时,让 StyleCop 满意的最佳方法是什么?

例如:

class Program
{
  static void Main(string[] args)
  {
     var t = DownloadSomethingAsync();

     Console.WriteLine(t.Result);
  }

  public delegate Task<string> TheDelegate(string page);

  static async Task<string> DownloadSomethingAsync()
  {
     string page = "http://en.wikipedia.org/";

     var content = await GetPageContentAsync(page);

     return content;
  }

  static async Task<string> GetPageContentAsync(string page)
  {
     string result;

     TheDelegate getContent = GetNotOrgContentAsync;
     if (page.EndsWith(".org"))
     {
        getContent = GetOrgContentAsync;
     }

     result = await getContent(page);

     return result;
  }

  static async Task<string> GetOrgContentAsync(string page)
  {
     string result;

     using (HttpClient client = new HttpClient())
     using (HttpResponseMessage response = await client.GetAsync(page))
     using (HttpContent content = response.Content)
     {
        result = await content.ReadAsStringAsync();
     }

     return result;
  }

  static async Task<string> GetNotOrgContentAsync(string page)
  {
      return await Task.FromResult("Do not crawl these");
      // removing async will cause "Cannot implicitly convert type 'string' to 'System.Threading.Tasks.Task<string>'
  }

}

找到了解决方案 - 为 google 搜索创建此解决方案以便轻松查找。

您还可以使用此处提到的警告抑制:Suppress warning from empty async method

// 编辑以删除关于日志记录的争论,该问题与任何方式无关,仅作为示例。

// 编辑以强制要求异步,因为这会让人们感到困惑

【问题讨论】:

  • 那为什么是async这个方法呢?如果您不打算等待返回,请不要使用 async 修饰符。
  • 第二点基于您正在记录某些内容的评论。使用适当的日志框架,它们不是微不足道的事情,你自己构建并且你会;根本不需要担心事情的异步方面。
  • async 不是签名的一部分。从外面看,没有人知道你是否使用了async,只是它返回一个Task 或一些Task&lt;T&gt;
  • @DavidG 我想知道你在哪里读到 OP 没有使用正确的日志框架
  • @huysentruitw 日志框架往往不使用异步方法。

标签: c# asynchronous async-await stylecop


【解决方案1】:

如果你没有await 任何东西,那么只需从方法声明中删除async 关键字并返回Task.CompletedTask

public override Task DoMyThing()
{
    // ..
    return Task.CompletedTask; // or Task.FromResult(0); in pre .NET Framework 4.6
}

因为基类中的虚方法标记为async,并不意味着覆盖也需要标记为asyncasync 关键字不是方法签名的一部分。

【讨论】:

  • 另外值得注意的是这个changes the semantics of the method,特别是关于如何处理异常。
  • 值得注意吗?我从来没有想过,但是抛出不同的异常是有道理的,但最后,在这两种情况下,异常都会被抛出,冒泡并包含完全相同的调用堆栈,对吧?
  • 不带async,直接同步抛出异常;使用await,异常被捕获并放置在返回的Task 上。调用堆栈(本质上)是相同的;但传播方式不同。
【解决方案2】:

选项:

在你的异步函数中添加一些代码:

return await Task.FromResult("Do not crawl these");

跨项目抑制:

#pragma warning disable 1998

或抑制一种方法:

#pragma warning disable 1998
async Task Foo() {}
#pragma warning restore 1998

【讨论】:

  • 你为什么要等待Task.FromResult(0)而不是直接返回?
  • 如果你真的想使用这个hack,至少用await Task.CompletedTask;替换,以避免创建无用的任务
  • 有些地方会阻止代码签入,直到所有 StyleCop 警告都得到解决。如果您在一个具有异步功能的方法中,即使该方法为空,StyleCop 也会强制等待。
猜你喜欢
  • 2015-07-07
  • 2017-04-30
  • 2019-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-27
  • 1970-01-01
  • 2014-02-13
相关资源
最近更新 更多