加了async 和不加的区别

超级大咸鱼 2020-07-24 10:04:14
这里有两个方法

public override Task<ClassA> GetClassA()
{
return Task.Run(()=>{
ClassA a = new ClassA();
return a;
});
}



public override async Task<ClassA> GetClassA()
{
return await Task.Run(()=>{
ClassA a = new ClassA();
return a;
});
}


这2个方法除了写法上不同 有其他区别吗?
...全文
8580 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
github_36000833 2020-07-27
  • 打赏
  • 举报
回复
引用 3 楼 正怒月神 的回复:
这个要分开说。 加不加 async,是一样的。 但是加了async后,加不加await。是不一样的。
+1 至于楼主问题,两个方法在逻辑上一样,但运行上有区别的。 原因是: 一、await会带来上下文切换; 二、await需要捕获当前的"运行上下文"(ExecutionContext),以便随后重施。该捕获保证了异步运行的代码,可以有相同的LogicalCallContext,SecurityContext等,并支持回到当前SynchronizationContext等,但捕获也带来了稍许的额外开销。 因此,无需顾虑使用async await。但是,如果是楼主的方法一,就最好不加await。 网上有roslyn请求,希望编译器能自动侦测尾部await调用,并自动优化为方法一写法,但目前该请求还处于‘开放’状态(https://github.com/dotnet/roslyn/issues/1981)。
xuzuning 2020-07-24
  • 打赏
  • 举报
回复
asyn 异步,用脑袋想不明白的话,可以到MSDN坐坐
OrdinaryCoder 2020-07-24
  • 打赏
  • 举报
回复
加了 async和await 的 返回的Task的Result是 一个new好的ClassA对象 因为await 会等Task.Run里的内容执行完 而没加async和await的 返回的Task的Result是null 因为在函数执行结束的时候Task.Run里的内容还没开始跑
  • 打赏
  • 举报
回复
上面少了一个 async,应该改为:
public override async Task<ClassA> GetClassA()
{
await Tasks.Yield();
ClassA a = new ClassA();
return a;
}


总之,你原本可以定义一个
public override ClassA GetClassA()
返回类型的方法,你现在却定义为 Task<ClassA> 作为函数返回值这本身应该算是增加了一层繁琐。当然,为了实现某种接口规格而返回 Task,那么你可以使用 await Tasks.Yield。实际上可以不考虑 Task.Run。

再次强调一下,没有必要使用 Task.Run(......) 的时候,其实使用 async/await 语法更清爽、贴切。
  • 打赏
  • 举报
回复
例如异步方法
        public static async Task t()
{
var web = new WebClient();
var r = await web.UploadDataTaskAsync("http://localhost:12341", Encoding.UTF8.GetBytes("spsp1234"));
var s = Encoding.UTF8.GetString(r);
Debug.Assert(s.StartsWith("path 长度="));
}


这里因为有 await,以顺序语句的语法来演绎并发异步操作之实,显然 async/await 少一层 Task 封装,比较清晰。

一个大方法中可能有许多 await,甚至是在循环结构中使用await。而你举出的例子“刻意地”是可以不用 await 的例子,其实这类方法不需要定义 Task 作为函数返回值,或者可以写成
public override Task<ClassA> GetClassA()
{
await Tasks.Yield();
ClassA a = new ClassA();
return a;
}


如果你在本不存在的问题上制造繁琐,那么其实就烦恼了。
  • 打赏
  • 举报
回复
实际上更贴切地写法是
public override Task<ClassA> GetClassA()
{
ClassA a = new ClassA();
return Task.FromResult(a);
}


从方便清晰贴切的语义角度看,async 显然是让特定的一些返回 Task<> 的方法更易读更贴切的一种“语法糖”。
正怒月神 2020-07-24
  • 打赏
  • 举报
回复
async只是告知,这可能是一个异步。 当async+await,才是异步。
正怒月神 2020-07-24
  • 打赏
  • 举报
回复
这个要分开说。 加不加 async,是一样的。 但是加了async后,加不加await。是不一样的。

110,567

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧