忽略异步而不等待编译警告
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<IHttpActionResult>
:
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<System.Web.Http.Results.ResponseMessageResult>' to 'System.Threading.Tasks.Task<System.Web.Http.IHttpActionResult>'
@Ivan-MarkDebono 将代码更改为Task.FromResult<IHttpActionResult>(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。
【讨论】:
然后您创建一个隐藏类的新对象,在其上调用使用该缓存已完成任务的方法,然后对该对象进行垃圾回收。我不是在谈论该方法是await
ing 的任务,我是在谈论它返回的任务。同样,它不是一个严重的打击,但它“不会降低性能”也不是真的。
@JonHanna 所有选项都必须返回一个新任务。
@JonHanna 但如果您指的是由异步方法生成的状态机,那么它也是在原始代码中生成的,因此没有降级
@JonHanna 此外,该状态机是一个结构,仅当您真正挂起该方法时才移动到堆,而等待的任务完成时不会发生这种情况。所以没有分配,没有收集,也没有降级。
你是对的,没有分配。除非涉及的方法被内联,否则还有比 Yuval 的答案更多的工作。以上是关于忽略异步而不等待编译警告的主要内容,如果未能解决你的问题,请参考以下文章