async/await 与 Task的区别

BXS_null 2018-09-18 03:23:39

static int ces()
{
Thread.Sleep(100);//模拟程序耗时
Console.WriteLine("子线程");
return 2;
}
static async Task<int> ces2()
{
return await Task.Run(() =>
{
Thread.Sleep(100);//模拟程序耗时
Console.WriteLine("子线程");
return 2;
});
}

static void Main(string[] args)
{
DateTime st = DateTime.Now;
Console.WriteLine("主线程开始");
//int r=Task.Run(()=> ces()).Result;
Task<int> task = ces2();
int r = task.Result;
Console.WriteLine("主线程结束");
Console.WriteLine("用时"+r+"_"+ + (DateTime.Now - st).TotalMilliseconds);
}


async await跟Task有什么区别,我运行了几次看他们耗时都是差不多的
...全文
1069 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_43238202 2018-09-19
  • 打赏
  • 举报
回复
那是当然的!每一条代码的执行时间,并不会因为执行环境的变化而改变(除非换台机器)
async await 只是:将异步调用以同步方式的形式书写
RandomWolf 2018-09-19
  • 打赏
  • 举报
回复
之前和帖主一样,遇到同样的困惑。最后也是用async await去解决的。代码好写。
但实际底层还是ThreadPool
BXS_null 2018-09-19
  • 打赏
  • 举报
回复
好 ,了解了 感谢各位大佬。大家说的对我的理解都很有帮助,之前模模糊糊的搞不清楚,现在就感觉明了一点了
BXS_null 2018-09-19
  • 打赏
  • 举报
回复
引用 27 楼 zmidl 的回复:
楼主是不是听了还是一头雾水? 楼上所有人说来说去 说不到重点,我来说吧。 首先 async await 不是你这么用的 你要异步不阻塞UI 用task 你要同步上下文且不阻塞UI 用async + await 包装 实现了用同步编程的写法实现异步 举个例子: (Task的场景)你有个监控界面,点击一个开始按钮,你用Task异步启动一个B函数经过一段时间计算吧结果显示到界面对吧Task用的很好。 (asnyc+await的场景) 你有个登录界面,输入用户信息后你点击登录按钮,这个时候你用为了不阻塞UI 你用Task异步执行B函数去对比数据库的用户信息对吧。但是这样做就直接跳转到了下一个界面了,没有等待你的B函数的结果啊。你的意图是要有了B函数结果再去判断是否进入下一个界面,那么这个时候你又要同步模式组织逻辑又要不阻塞UI 怎么办呢?以前用回调在回调函数里处理逻辑,现在用asnyc+await以同步方式实现异步就可以更加方便的解决这个问题了。
好谢谢,这个例子可以理解
正怒月神 2018-09-19
  • 打赏
  • 举报
回复
当async await一起使,是异步。
当仅仅是Task.Result时,是同步。

测试代码:
static void Main(string[] args)
{
Console.WriteLine("开始");
Task<int> t = Test1();
int a = t.Result;
Test1();

Console.WriteLine("结束");

Console.ReadLine();
}

static async Task<int> Test1()
{
await Task.Delay(500);
Console.WriteLine("2");
return 2;
}
zmidl 2018-09-19
  • 打赏
  • 举报
回复
楼主是不是听了还是一头雾水? 楼上所有人说来说去 说不到重点,我来说吧。
首先 async await 不是你这么用的
你要异步不阻塞UI 用task
你要同步上下文且不阻塞UI 用async + await 包装 实现了用同步编程的写法实现异步
举个例子:
(Task的场景)你有个监控界面,点击一个开始按钮,你用Task异步启动一个B函数经过一段时间计算吧结果显示到界面对吧Task用的很好。
(asnyc+await的场景) 你有个登录界面,输入用户信息后你点击登录按钮,这个时候你用为了不阻塞UI 你用Task异步执行B函数去对比数据库的用户信息对吧。但是这样做就直接跳转到了下一个界面了,没有等待你的B函数的结果啊。你的意图是要有了B函数结果再去判断是否进入下一个界面,那么这个时候你又要同步模式组织逻辑又要不阻塞UI 怎么办呢?以前用回调在回调函数里处理逻辑,现在用asnyc+await以同步方式实现异步就可以更加方便的解决这个问题了。
SoulRed 2018-09-19
  • 打赏
  • 举报
回复
异步是基于task 进行的更方便的写法。
  • 打赏
  • 举报
回复
一个真正的(而不是仅仅用个 Task 形式的)异步程序是这样写的
using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{
class Program
{
static async Task<int> ces2()
{
return await Task.Run(() =>
{
Thread.Sleep(100);//模拟程序耗时
Console.WriteLine("子线程");
return 2;
});
}

static async void test()
{
Console.WriteLine("结果是{0}", await ces2());
}

static void Main(string[] args)
{
DateTime st = DateTime.Now;
Console.WriteLine("主线程开始");
test();
Console.WriteLine("主线程结束。按任意键结束......");
Console.ReadKey();
}
}
}

或者更清晰的写法
using System;
using System.Threading.Tasks;

namespace ConsoleApp1
{
class Program
{
static async Task<int> ces2()
{
await Task.Delay(100);
Console.WriteLine("子线程");
return 2;
}

static async void test()
{
Console.WriteLine("结果是{0}", await ces2());
}

static void Main(string[] args)
{
DateTime st = DateTime.Now;
Console.WriteLine("主线程开始");
test();
Console.WriteLine("主线程结束。按任意键结束......");
Console.ReadKey();
}
}
}

所以说,如果思维上是“同步阻塞”的,那么写出来的程序也就不会异步。
  • 打赏
  • 举报
回复
异步编程风格,本质上就是“回调”,也就是在任务完成时(在线程池分配的其它线程或者当前线程——假设当前线程已经闲置的情况下)才委托回调 await 后边的代码。所以 await 是明确地说要回调编程,要异步风格编程。

不管同步阻塞还是异步编程,这里的前提都是使用 Task 框架。但是同步阻塞当前线程,那么可以说使用高大上的 Task 就功亏一篑了。所以说如果只会使用 Task 而写同步阻塞代码,是很 low 的事情啦。
  • 打赏
  • 举报
回复
是的,写
task.Result
这类代码只有“不得已”的时候才写。使用一个异步编程框架但是写成同步阻塞代码,本身是很 low 的事情,所以有这个同步阻塞功能,那是给初学者用的。而你设计异步多线程并发算法时,如果你的思路是异步多线程并发的,你就会用好 Task 的异步能力,而不会用烂 Task。
BXS_null 2018-09-18
  • 打赏
  • 举报
回复
引用 16 楼 wanghui0380 的回复:
也就是说,async意思其实是,那怕他还在运行,也并不妨碍我们对未来的结果进行编写。语义上则是“我cpu不必等着他结束,他执行他的,我继续规划我的,我不必搬个板凳坐在电视机前等着彩票开奖”
如果在传统的Task里面在套一个Task好像是一样的?
BXS_null 2018-09-18
  • 打赏
  • 举报
回复
引用 16 楼 wanghui0380 的回复:
进行编写。语义上则是“我cpu不必等着他结束,他执行他的,我继续规划我的,我不必搬个板凳坐在电视机前等着彩票开奖”
哦哦哦,哈哈 现在懂了。比如说我需要异步里面的返回值来做一些操作,如果传统的Task的Result方法就需要等待异步执行结束主线程才能执行接下来的。如果使用 async方法的话,就相当把异步的返回值放到 async方法里面来做操作,而且主线程不用等待。哦。async/await修饰的方法也相当于一个异步方法吗?
lindexi_gd 2018-09-18
  • 打赏
  • 举报
回复
关于 await 请看 [如何实现一个可以用 await 异步等待的 Awaiter - walterlv](https://walterlv.com/post/write-custom-awaiter.html )
lindexi_gd 2018-09-18
  • 打赏
  • 举报
回复
引用 15 楼 u010941149 的回复:
await就是编译器为你写的代码,await不是用来提高程序运行速度的,await的作用在于并行和并发 Task 就是线程池线程,它是充分利用计算机内核,提高程序运行速度 await在Task的上面包装了一层,把你的那个线程池里面的线程的结果取出来,执行你注册的回调函数
协程
wanghui0380 2018-09-18
  • 打赏
  • 举报
回复
有一点不是很明白。使用Task 的时候我要获取返回值 int r=Task.Run(()=> ces()).Result;这样,ces方法里面也只需要写一个return就可以了。
async/await 的话 int r = ces2().Result; ces2方法里面也是要把ces里面的代码写一遍。这样感觉就是一样的啊?

那是因为async其实是返回了一个正在执行,且未来有结果的task。
而你直接返回的是,他已经执行完了,并且把执行结果返回了。


比如说,我卖张彩票

我async的意思是,现在彩票还没开奖,我现在就可以畅想“如果彩票中奖了,我要环球旅行这件事情”

而非async意思是,等彩票开奖了,我如果中奖了,我要环球旅行。

也就是说,async意思其实是,那怕他还在运行,也并不妨碍我们对未来的结果进行编写。语义上则是“我cpu不必等着他结束,他执行他的,我继续规划我的,我不必搬个板凳坐在电视机前等着彩票开奖”
sdfgrtyu 2018-09-18
  • 打赏
  • 举报
回复
await就是编译器为你写的代码,await不是用来提高程序运行速度的,await的作用在于并行和并发

Task 就是线程池线程,它是充分利用计算机内核,提高程序运行速度

await在Task的上面包装了一层,把你的那个线程池里面的线程的结果取出来,执行你注册的回调函数





BXS_null 2018-09-18
  • 打赏
  • 举报
回复
引用 13 楼 u010941149 的回复:
你写的这段代码能运行吗? 你写的代码有问题,你那个基于await的语句需要获取上下文线程,然后你又获取result,你这代码是死锁吧,,,,,,
额,能运行。死锁怎么说?或出现什么问题
sdfgrtyu 2018-09-18
  • 打赏
  • 举报
回复
你写的这段代码能运行吗?
你写的代码有问题,你那个基于await的语句需要获取上下文线程,然后你又获取result,你这代码是死锁吧,,,,,,





xuzuning 2018-09-18
  • 打赏
  • 举报
回复
你 int r=Task.Run(()=> ces()).Result; 本是就是同步写法
并无 async/await 的必要
BXS_null 2018-09-18
  • 打赏
  • 举报
回复
引用 6 楼 wanghui0380 的回复:
至于我们为啥要基于未来,那是因为异步。 我这事情可以先跑,甚至我可以同时跑几个未来任务,我只是要求当他未来执行完毕后通知我去执行后续的任务(当然,对于未来结果来说,我还得说未来是执行成功了,还是执行失败了,还是超时了,还是cancel了,还是异常了) 就像上面说的,他是语法糖,你可以像编写同步代码一样去编写异步代码,而没这个语法糖,你就的自己去编写传统异步代码
有一点不是很明白。使用Task 的时候我要获取返回值 int r=Task.Run(()=> ces()).Result;这样,ces方法里面也只需要写一个return就可以了。 async/await 的话 int r = ces2().Result; ces2方法里面也是要把ces里面的代码写一遍。这样感觉就是一样的啊?
加载更多回复(10)

110,539

社区成员

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

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

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