忽略异步而不等待编译警告

Posted

技术标签:

【中文标题】忽略异步而不等待编译警告【英文标题】:Ignore async without await compilation warning 【发布时间】:2015-08-10 15:22:00 【问题描述】:

我有一个具有以下抽象方法的基本控制器:

[HttpDelete]
public abstract Task<IHttpActionResult> Delete(int id);

在一个特定的控制器中,我不想实现删除,所以方法如下:

public override async Task<IHttpActionResult> Delete(int id)

    return ResponseMessage(Request.CreateResponse(HttpStatusCode.MethodNotAllowed, new NotSupportedException()));

虽然上面的代码可以编译,但我得到一个警告:

此异步方法缺少“等待”运算符,将同步运行。考虑使用 'await' 运算符来等待非阻塞 API 调用,或使用 'await Task.Run(...)' 在后台线程上执行 CPU 密集型工作。

除了忽略上面的警告,有没有更好的选择(即改变上面的代码),这样这个警告就不会发生?

编辑

我把这行改成:

return await Task.Run(() => ResponseMessage(Request.CreateResponse(HttpStatusCode.MethodNotAllowed, new NotSupportedException())));

这将删除警告。但是,有没有更好的解决方案?

【问题讨论】:

如果您不想允许删除操作,为什么要从它派生? 【参考方案1】:

除了忽略上面的警告,有没有更好的选择 (即更改上面的代码)以便不会出现此警告?

替代方法是删除async 修饰符并使用Task.FromResult 返回Task&lt;IHttpActionResult&gt;

public override Task<IHttpActionResult> Delete(int id)

    return Task.FromResult<IHttpActionResult>(
                ResponseMessage(Request.CreateResponse(
                                        HttpStatusCode.MethodNotAllowed,
                                        new NotSupportedException())));

【讨论】:

有了上面的答案,我得到了以下异常:Cannot implicitly convert type 'System.Threading.Tasks.Task&lt;System.Web.Http.Results.ResponseMessageResult&gt;' to 'System.Threading.Tasks.Task&lt;System.Web.Http.IHttpActionResult&gt;' @Ivan-MarkDebono 将代码更改为Task.FromResult&lt;IHttpActionResult&gt;(ResponseMessage(...));【参考方案2】:

虽然 Yuval's answer 关于完全删除 async 通常是删除警告的首选方法,但另一个不会降低性能的正确答案是 await 已完成的任务。

await 大致翻译为检查等待的任务是否完成,如果是则继续同步执行其余的方法,如果没有则添加其余的作为该任务的延续。

private static readonly Task _completedTask = Task.FromResult(false);
public override async Task<IHttpActionResult> Delete(int id)

    await _completedTask;
    return ResponseMessage(Request.CreateResponse(HttpStatusCode.MethodNotAllowed, new NotSupportedException()));

在 .Net 4.6 中,您可以使用新的 Task.CompletedTask 属性,而不是创建自己的已完成任务。

这使您可以保留方法 async 并使用它保留 same error-handling semantics。

【讨论】:

然后您创建一个隐藏类的新对象,在其上调用使用该缓存已完成任务的方法,然后对该对象进行垃圾回收。我不是在谈论该方法是awaiting 的任务,我是在谈论它返回的任务。同样,它不是一个严重的打击,但它“不会降低性能”也不是真的。 @JonHanna 所有选项都必须返回一个新任务。 @JonHanna 但如果您指的是由异步方法生成的状态机,那么它也是在原始代码中生成的,因此没有降级 @JonHanna 此外,该状态机是一个结构,仅当您真正挂起该方法时才移动到堆,而等待的任务完成时不会发生这种情况。所以没有分配,没有收集,也没有降级 你是对的,没有分配。除非涉及的方法被内联,否则还有比 Yuval 的答案更多的工作。

以上是关于忽略异步而不等待编译警告的主要内容,如果未能解决你的问题,请参考以下文章

在C#中使用async而不等待?

如何获得warnings.warn发出警告而不忽略该行?

Qt使用MinGW编译,如何忽略警告

VS2013 忽略编译指示警告禁用

iOS编程 手动忽略clang编译器警告

iOS常用的忽略警告