Node.js和.Net 4.5下的await,async和await相比有什么不同

ASP.NET(46)
本人是从.NET4.0刚出的时候接触的.NET环境,所以学的东西就是4.0及其之前的。时代飞速前进,目测5.0也快出了吧,但一直也没去接受新的技术。最近由于要学习Web API,快看完了,却发现4.5已经大行其道了,于是又进行补脑。async与await便是其中之一:
  这是两个关键字,用于异步编程。我们传统的异步编程方式一般是Thread、ThreadPool、BeginXXX、EndXXX等等。把调用、回调分开来,代码的逻辑是有跳跃的,于是会导致思路不是很清晰的问题,在.NET 4.5中,新推出的async、await关键字,可以帮助我们像写同步方法一样去写异步方法(保证代码的整齐清晰)。
  先来看个传统同步方法例子:
static void Main(string[] args)
Console.WriteLine("同步方式测试开始!");
SyncMethod(0);
Console.WriteLine("同步方式结束!");
Console.ReadKey();
private static void SyncMethod(int input)
Console.WriteLine("进入同步操作!");
var result = SyancWork(input);
Console.WriteLine("最终结果{0}", result);
Console.WriteLine("退出同步操作!");
private static int SyancWork(int val)
for (int i = 0; i & 5; ++i)
Console.WriteLine("耗时操作{0}", i);
Thread.Sleep(100);
  可以从右图中看到执行结果,是非常典型的同步执行方法。
  async关键字能用在方法、lambda表达式的声明部分,用来标示此方法可能包含await关键字,只有拥有async才能在其内部使用await关键字。异步方法可以具有Task、Task&&或void的返回类型;await关键字则是用于返回值是“可等待”类型(awaitable)的方法或lambda表达式内,“awaitable”可以是任何类型(常见的有Task、Task&&),它必须公开一个GetAwaiter() 方法并且返回有效的”awaiter”。更详细的信息可以参考“关于Async与Await的FAQ”,里面介绍了这些概念与注意事项。
  当一个async方法,且内部包含await关键字,它就会在编译的时候成为一个异步方法,如果没有await关键字,则它将只会被当成一个同步方法来执行。如果对其内部实现感兴趣可以参考“异步性能:了解 Async 和 Await 的成本”一文,相信对深入了解这种机制还是有所帮助的。
  现在我们尝试使用新出的异步关键字async、await来改造成异步调用:
static void Main(string[] args)
Console.WriteLine("\n异步方式测试开始!");
AsyncMethod(0);
Console.WriteLine("异步方式结束!");
Console.ReadKey();
private static async void AsyncMethod(int input)
Console.WriteLine("进入异步操作!");
var result = await AsyncWork(input);
Console.WriteLine("最终结果{0}", result);
Console.WriteLine("退出异步操作!");
private static async Task&int& AsyncWork(int val)
for (int i = 0; i & 5; ++i)
Console.WriteLine("耗时操作{0}", i);
await Task.Delay(100);
  先来看结果吧,我们发现耗时操作已经是异步进行了。整体流程大概是先由Main函数异步调用AsyncMethod,并不等待AsyncMethod完成,继续往下执行。而AsyncMethod方式在被调用后,在分配到时间片时开始启动,执行函数体内容,并由于await AsyncWork语句而继续异步调用AsyncWork,但由于await关键字,将在此等待AsyncWork完成后,再继续往下执行。那么,AyncWork也一样的,被调用后,在分配到时间片时开始启动,执行耗时操作。
  可以看到,使用了新的关键字后,同步与异步编程的语法差别进一步减少。随着.NET 4.5的推出,许多新类库和既有类库都支持这种新型的异步语法(比如HttpClient、HttpServer、MemoryStream…),它们以类似ReadAsync、WriteAsync、SendAsync等分开方法来提供具有async声明,且返回类型为Task、Task&&的异步工作方式。
  补充:
  刚才有朋友提到await Task.Delay(100)这条语句,这是为了让AsyncWork成为异步方法才加的,如果你要进行的操作不支持await修饰怎么办,其实很简单,使用Task.Factory.StartNew()就行了,举例:
private static async void AsyncMethod(int input)
Console.WriteLine("进入异步操作!");
var result = await Task.Factory.StartNew((Func&object, int&)SyncWork2, input);
Console.WriteLine("最终结果{0}", result);
Console.WriteLine("退出异步操作!");
private static int SyncWork2(object input)
int val = (int)
for (int i = 0; i & 5; ++i)
Console.WriteLine("耗时操作{0}", i);
Thread.Sleep(100);
  这样,我们的SyncWork2实际上却是异步执行的,所得结果与前面的异步方法一致,只是这样一来输入参数只能是object类型,需要进行类型转化。另外,除了StartNew,我们还可以新建一个Task,然后调用Run,以完成同样效果。
  目前来说,这种异步工作还是会造成本人使用上的不适,不过如果在将来的版本中,继续推广使用,相信不久便能熟练,且加快写代码的速度,编写出逻辑清晰的代码。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:139620次
积分:2827
积分:2827
排名:第7763名
原创:139篇
转载:43篇
评论:16条
(1)(1)(2)(2)(2)(6)(4)(5)(1)(4)(5)(3)(17)(5)(10)(2)(1)(1)(1)(1)(2)(2)(1)(3)(2)(1)(7)(1)(4)(11)(4)(3)(19)(48)在MVC中使用async和await的说明 - billpeng - 博客园
技术源自生活
posts - 245, comments - 86, trackbacks - 0, articles - 0
首先,在mvc中如果要用纯异步请不要使用async和await,可以直接使用Task.Run。
其次,在mvc中使用async和await可以让系统开新线程处理Task的代码,同时不必等Task执行结束,就可以同时运行Task之后的代码,加快效率。
要注意的是:如果使用async和await,系统虽然可以同时处理多个事务,但客户端(浏览器)不会有响应,依然要等到所有代码全部执行完毕(包括异步的代码)才能正常响应。
* 演示如何利用 .net 4.5 的新特性实现异步操作
* 什么场景下需要异步操作?
* 在因为磁盘io或网络io而导致的任务执行时间长的时候应该使用异步操作,如果任务执行时间长是因为cpu的消耗则应使用同步操作(此时异步操作不会改善任何问题)
* 原理是什么?
* 在 Web 服务器上,.NET Framework 维护一个用于服务 ASP.NET 请求的线程池(以下把 .NET Framework 维护的用于服务 ASP.NET 请求的线程池称作为&特定线程池&)
* 同步操作时,如果特定线程池利用满了,则不会再提供服务
* 异步操作时:
* 1、一个请求过来,特定线程池出一个线程处理此请求
* 2、启动一个非特定线程池中的另一个线程处理异步操作,此时处理此请求的线程就会空出来,不会被阻塞,它可以继续处理其它请求
* 3、异步操作执行完毕后,从特定线程池中随便找一个空闲线程返回请求结果
实际工作中,async和await我们可以用于类似用户上传头像、上传照片这种的耗时较长的功能中,我们可以在边上传照片时边处理数据库的其他事务。
而纯异步则多用于时间较长,而无需结果实时看反馈给用户的操作,例如:管理在后台备份数据库、清理垃圾文件等。
如果async和await的异步方法是有返回值的,而且主方法中又要使用这个返回值,那么将不会实现多个异步方法同时执行,要等异步结果后才继续执行,相当于异步并未起到多程序同时处理事务的目的。这仅是对于Web或控制台程序而言的,如果对于Winform则有大大的不同,因为Winform如果使用异步时界面是可以响应的。
Web中异步更多的是用来实现大量IO操作,或大量调用WCF、WebService时使用。
所以,在Mvc这种Web界面中使用async和await异步的实际意义就不是很大了,因为界面总是没有响应的,而且也无法实现多线程同时工作。
有需要请看这篇:
async的作用是异步执行,await的作用是等待执行结果(会卡住异步方法中await以下的代码,但不会卡死主线程)。
async一般最终都需要一个async void方法来进行最高层的调用。比如:private async void Sync_Button_Click(object sender, RoutedEventArgs e),C#中也提供了大量的可设置async的系统方法和事件。
class Program
private static async void Test()
Task&int& t = new Task&int&(() =& { Thread.Sleep(3000); return 1; });
t.Start();
int tr = await
Console.WriteLine(tr);
static void Main(string[] args)
Console.WriteLine("Main");
Console.ReadKey();
&Test函数就用最简单的方法使用了这两个关键字,执行这段代码,首先输出&Main&,然后3秒钟后会输出&1&。
&也可以使用:
using System.Collections.G
using System.L
using System.T
using System.T
using System.Threading.T
namespace ConsoleApplication11
class Program
static void Main(string[] args)
Console.WriteLine("Main");
Console.ReadKey();
private static async void Test()
var t = Task&int&.Run(() =& { Thread.Sleep(3000); return 1; });
Console.WriteLine(await t);
使用async异步编程时,请注意如下事项:
async void函数只能在UI Event回调中使用。
async void函数中一定要用try-catch捕获所有异常,否则会很容易导致程序崩溃。
async void类型的lambda表达式非常隐蔽,并且容易在无意中编写出来,尤其需要注意。
不要忽视CS4014告警,更不要为了消除CS4014告警而改用async void函数。确实无需等待的async&Task函数用我前面写的扩展函数IgnorCompletion消除这个告警。
注册TaskScheduler.UnobservedTaskException事件,记录Task中未处理异常信息,方便分析及错误定位。(注意,这个回调里面不能进行耗时操作,具体原因参看前面的老赵的那篇Blog)
private async void Sync_Button_Click(object sender, RoutedEventArgs e) {
OutputTextBlock.Text += "開始" + Environment.NewL
// 這裡會等 getFileContentAsync() 執行完畢後, 再執行貼上結束字串那一行
// 因為 Compiler 會再 await 這行下斷點
OutputTextBlock.Text += await getFileContentAsync();
OutputTextBlock.Text += "結束" + Environment.NewL
9: private async Task&string& getFileContentAsync() {
StorageFolder folder = KnownFolders.DocumentsL
StorageFile file = await folder.GetFileAsync(TESTED_FILE_NAME);
var result = await FileIO.ReadTextAsync(file) + Environment.NewL

我要回帖

更多关于 nodejs async await 的文章

 

随机推荐