C#异步方法返回void与Task的区别详解

作者:金庆 时间:2021-06-29 10:00:35 

C#异步方法返回void和Task的区别

如果异步(async关键字)方法有返回值,返回类型为T时,返回类型必然是 Task<T>。

但是如果没有返回值,异步方法的返回类型有2种,一个是返回 Task, 一个是返回 void:


public async Task CountDownAsync(int count)
{
 for (int i = count; i >= 0; i--)
 {
  await Task.Delay(1000);
 }
}

public async void CountDown(int count)
{
 for (int i = count; i >= 0; i--)
 {
  await Task.Delay(1000);
 }
}

调用时,如果返回 Task, 但返回值被忽略时,VS 会用绿色波浪线警告:


CountDownAsync(3);
~~~~~~~~~~~~~~~~~

信息为:

(awaitable) Task AsyncExample.CountDownAsync(int count)

Usage:
 await CountDownAsync(...);

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

中文为:

CS4014:由于此调用不会等待,因此在此调用完成之前将会继续执行当前方法。请考虑将"await"运算符应用于调用结果。

添加 await 后就正常了:


await CountDownAsync(3);

如果调用者不是一个异步方法,因为只有在异步方法中才可以使用 await,

或者并不想在此等待,如想同时执行多个 CountDownAsync(),

就不能应用 await 来消除警告。

此时可以改用 void 返回值的版本:


void Test()
{
...
CountDown(3);
CountDown(3);
...
}

async void CountDown(int count)
{
for (int i = count; i >= 0; i--)
{
 await Task.Delay(1000);
}
}

Never call async Task methods without also awaiting on the returned Task. If you don't want to wait for the async behaviour to complete, you should call an async void method instead.

摘自:http://www.stevevermeulen.com/index.php/2017/09/using-async-await-in-unity3d-2017/

CountDown() 可以直接调用 CountDownAsync() 实现:


async void CountDown(int count)
{
await CountDownAsync(count);
}

使用下划线变量忽略异步方法的返回值也可以消除警告:


void Test()
{
...
_ = CountDownAsync(3);
_ = CountDownAsync(3);
...
}

但是这样同时也会忽略 CountDownAsync() 中的异常。如以下异常会被忽略。


void Test()
{
...
_ = CountDownAsync(3);
...
}

async Task CountDownAsync(int count)
{
for (int i = count; i >= 0; i--)
{
 await Task.Delay(1000);
}
throw new Exception();
}

如果是调用返回 void 的异步方法,Unity 会报错:

Exception: Exception of type 'System.Exception' was thrown.

对 Async 后缀的说明

You could say that the Async suffix convention is to communicate to the API user that the method is awaitable. For a method to be awaitable, it must return Task for a void, or Task<T> for a value-returning method, which means only the latter can be suffixed with Async.

摘自:https://stackoverflow.com/questions/15951774

grpc 生成的代码中,异步请求返回了一个 AsyncCall 对象,AsyncCall 实现了 GetAwaiter() 接口:


 public virtual grpc::AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, ...)

可以这样调用并等待:


var resp = await client.GetFeatureAsync(req);

虽然返回类型不是Task<>, 但是可等待,所以添加了 Async 后缀。

总结

来源:https://blog.csdn.net/jq0123/article/details/114064557

标签:c#,异步,返回
0
投稿

猜你喜欢

  • 详解Java如何实现小顶堆和大顶堆

    2023-11-10 04:03:05
  • c# DevExpress gridcontrol日期行的显示格式设置

    2022-07-11 05:28:52
  • c语言轻松实现猜数字小游戏

    2021-10-21 23:42:13
  • 提权函数之RtlAdjustPrivilege()使用说明

    2021-08-27 04:16:49
  • C# 站点IP访问频率限制 针对单个站点的实现方法

    2023-09-23 18:35:30
  • Java的Struts框架中登陆功能的实现和表单处理器的使用

    2022-05-20 23:44:45
  • SpringBoot自定义maven-plugin插件整合asm代码插桩

    2021-05-24 02:15:49
  • 使用Maven Helper解决Maven插件冲突的方法

    2023-11-08 06:07:05
  • java实现ftp文件上传下载功能

    2023-04-13 19:31:30
  • java与JSON数据的转换实例详解

    2022-07-03 22:48:25
  • C#实现收发邮件功能

    2021-09-20 19:40:46
  • c# 曲线图生成代码

    2023-03-27 07:52:55
  • 详解C#中使用对象或集合的初始值设定项初始化的操作

    2021-12-25 20:04:52
  • C# WebApi 接口返回值不困惑:返回值类型详解

    2022-05-06 13:16:35
  • C#文件路径操作详细总结

    2021-06-06 04:07:41
  • SpringBoot深入探究@Conditional条件装配的使用

    2021-08-18 00:06:53
  • JAVA List和Map切割工具详解

    2023-01-27 11:32:42
  • java为何不能多继承的原因详解

    2023-10-12 04:45:00
  • Java中DataInputStream和DataOutputStream的使用方法

    2023-02-03 04:08:28
  • Android 中 退出多个activity的经典方法

    2023-02-09 04:38:59
  • asp之家 软件编程 m.aspxhome.com