转 .NET4.5之初识async与await

简介: 来自:http://www.cnblogs.com/lekko/archive/2013/03/05/2944282.html      本人是从.NET4.0刚出的时候接触的.NET环境,所以学的东西就是4.0及其之前的。

来自:http://www.cnblogs.com/lekko/archive/2013/03/05/2944282.html  

 

 本人是从.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);
                val++;
            }
            return val;
        }

可以从右图中看到执行结果,是非常典型的同步执行方法。

  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);
                val++;
            }
            return val;
        }


先来看结果吧,我们发现耗时操作已经是异步进行了。整体流程大概是先由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)input;
            for (int i = 0; i < 5; ++i)
            {
                Console.WriteLine("耗时操作{0}", i);
                Thread.Sleep(100);
                val++;
            }
            return val;
        }

 这样,我们的SyncWork2实际上却是异步执行的,所得结果与前面的异步方法一致,只是这样一来输入参数只能是object类型,需要进行类型转化。另外,除了StartNew,我们还可以新建一个Task,然后调用Run,以完成同样效果。

  目前来说,这种异步工作还是会造成本人使用上的不适,不过如果在将来的版本中,继续推广使用,相信不久便能熟练,且加快写代码的速度,编写出逻辑清晰的代码。

 

相关文章
|
3天前
|
数据库 开发者
.NET 异步编程之谜:async/await 模式究竟隐藏着怎样的神奇力量?
【8月更文挑战第28天】在当今注重效率和响应性的软件开发领域,.NET 的 async/await 模式如同得力助手,简化异步代码编写,使代码更易理解和维护。通过后台执行耗时操作,如网络请求和数据库查询,避免阻塞主线程,显著提升系统响应性。此模式不仅适用于网络请求,还广泛应用于数据库操作和文件读写。合理使用 async/await 可大幅优化性能,但需注意避免过度使用、正确处理调用链及异常,以确保系统稳定性和高效性。深入探索 async/await,助您构建更出色的应用程序。
18 0
|
3月前
|
存储 IDE Java
【.NET Core】深入理解async 和 await 理解
【.NET Core】深入理解async 和 await 理解
51 0
C#.NET使用Task,await,async,异步执行控件耗时事件(event),不阻塞UI线程和不跨线程执行UI更新,以及其他方式比较
原文:C#.NET使用Task,await,async,异步执行控件耗时事件(event),不阻塞UI线程和不跨线程执行UI更新,以及其他方式比较 使用Task,await,async,异步执行事件(event),不阻塞UI线程和不跨线程执行UI更新   使用Task,await,async 的异步模式 去执行事件(event) 解决不阻塞UI线程和不夸跨线程执行UI更新报错的最佳实践,附加几种其他方式比较 由于是Winform代码和其他原因,本文章只做代码截图演示,不做界面UI展示,当然所有代码都会在截图展示。
4852 0
|
C# C++
.NET Core 控制台应用程序使用异步(Async)Main方法
C# 7.1 及以上的版本允许我们使用异步的Main方法
7538 0
|
Web App开发 API C#
.Net 4.5 异步编程初试(async和await)
前言   最近自己在研究Asp.Net Web API。在看到通过客户端来调用Web API的时候,看到了其中的异步编程,由于自己之前没有接触过,所以就稍微的学习了解一下。这两篇文章是: Calling a Web API From a .
1182 0
|
16天前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
26 0
|
16天前
|
开发框架 前端开发 安全
ASP.NET MVC 如何使用 Form Authentication?
ASP.NET MVC 如何使用 Form Authentication?
|
20天前
|
开发框架 .NET
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
72 0