当前位置:首页 > C#编程 > C#/.net框架 > 正文内容

MSDN中关于async/await异步编程的说明

Jorge2年前 (2022-05-09)C#/.net框架754

 先上一段代码,msdn中举得一个例子,勇哥将其改造了一下,如下:


C#
using System;using System.Collections.Generic;using System.Linq;using System.Net.Http;using System.Text;using System.Threading.Tasks;namespace ConsoleApplication16{
    class Program
    {
        static void Main(string[] args)
        {
            var s1= GetUrlContentLengthAsync();
            //var s3 = s1.Result;
            var s3=s1.GetAwaiter().GetResult();
            Console.ReadKey();
        }


        public static async Task<int> GetUrlContentLengthAsync()
        {
            var client = new HttpClient();

             Task<string> getStringTask =
                client.GetStringAsync("http://www.baidu.com/");

            DoIndependentWork();

            string contents =await getStringTask;
            DoIndependentWork2(contents);

            return contents.Length;
        }

         static void DoIndependentWork()
        {
            Console.WriteLine("Working...");
        }

        static void DoIndependentWork2(string msg)
        {
            Console.WriteLine(msg);
        }
    }}


注意这段异步代码的几个特征:

1. 方法签名处的async

2. 返回类型是 Task<int> 

   注意返回值是int型,而不要理解为Task类型。

3. 方法名以Async结束,这个只是一种约定。

4. 方法体中关键字 await,它至少应该有一个,在该处会暂停函数执行,直到等待异步操作完成方法才能继续。同时,将方法挂起,返回本函数的调用者。


异步编程中最需弄清的是控制流是如何从方法移动到方法的。 下图上对上述代码的执行流程的说明:


图中黑箭头是正常流程(普通的逐条语句运动的流程)

红色箭头是等待时将控制权返回函数调用者

青色箭头恢复函数挂起后继续运行的流程。

image.png


由图中我们可以知道:

1,2,3,4,5 是正常的同步运行流程,要注意的是函数client.GetStringAsync它也是个异步的,因此它不是阻塞的。

第6步,也就是await处,函数暂停执行,控制权转回函数的调用者。

第7步,异常方法GetStringAsync执行完毕,取得字符串。这时候程序恢复挂起状态,继续运行第7,8步,函数执行至返回。


因此在上面代码中除了第6步await是异步执行外,其它代码行都是同步执行的。



另外,一个异步方法中,看来一定是调用了另一个异步方法,这样才可以await等待,转移函数控制权给调用者。

这句话是勇哥总结的,不是msdn官方说的。也不知道对不对。请指正。




附录:


 异步方法可以具有以下返回类型:

Task(对于执行操作但不返回任何值的异步方法)。

Task<TResult>(对于返回值的异步方法)。

void(对于事件处理程序)。

从 C# 7.0 开始,任何具有可访问的 GetAwaiter 方法的类型。 GetAwaiter 方法返回的对象必须实现 System.Runtime.CompilerServices.ICriticalNotifyCompletion 接口。

从 C# 8.0 开始,IAsyncEnumerable<T> 返回异步流的异步方法 。


附录2:一个简单的winform下的异步小例子

C#
 1个按钮,2个textbox,下面这样可以正确异步,窗体也不会死掉,textBox2会先有结果,textBox1再有结果    private async void button1_Click(object sender, EventArgs e)
        {
            Does();
            textBox2.Text = "1";
        }


        private Task<string> DoWork()
        {
            return Task.Run(() =>
               {
            Thread.Sleep(4000);
            return "Done with work!";
               }
                );
        }
        private async void Does()
        {
            string text = await DoWork();
            textBox1.Text = text;
        }如果把按钮事件改成下面这样,窗体不会死,但不会异步执行   private async void button1_Click(object sender, EventArgs e)
        {
            textBox2.Text =await DoWork();
            textBox2.Text = "1";
        }


--------------------- 

作者:hackpig

来源:www.skcircle.com

版权声明:本文为博主原创文章,转载请附上博文链接!

扫描二维码推送至手机访问。

版权声明:本文由7点博客发布,如需转载请注明出处。

本文链接:http://6dot.cn/?id=83

标签: .NET.NET框架
分享给朋友:

“MSDN中关于async/await异步编程的说明” 的相关文章

C# 当List.Find()返回一个结构体对象时,如何判断它为空?

C# 当List.Find()返回一个结构体对象时,如何判断它为空?

请看演示程序。我们知道List.Find() 如果找到则返回这个对象,找不到返回这个类型的缺省值。下面例子中,你无法这样写:            if(res1==null)        &nbs...

C#的变迁史 - C# 4.0 之线程安全集合篇

C#的变迁史 - C# 4.0 之线程安全集合篇

作为多线程和并行计算不得不考虑的问题就是临界资源的访问问题,解决临界资源的访问通常是加锁或者是使用信号量,这个大家应该很熟悉了。  而集合作为一种重要的临界资源,通用性更广,为了让大家更安全的使用它们,微软为我们带来了强大的并行集合:System.Collections.Concurrent里面的各...

谈谈ObservableCollection观察者集合

谈谈ObservableCollection观察者集合

注:事件很常见,但有重复的代码量。如果你想简化一下事件的编程,而且是整个程序只使用一个像事件池一样的东西,可以尝试使用下文讲的ObservableCollection观察者集合来做到。ObservableCollection<T>类表示一个动态数据集合,在添加项,移除项或刷新整个列表时,...

索引器(C# 编程指南)

索引器(C# 编程指南)

 索引器允许类或结构的实例就像数组一样进行索引。 无需显式指定类型或实例成员,即可设置或检索索引值。 索引器类似于属性,不同之处在于它们的访问器需要使用参数。以下示例定义了一个泛型类,其中包含用于赋值和检索值的简单 get 和 set 访问器方法。&...

C# 异步和等待,async/await

C# 异步和等待,async/await

 首先,重点是:异步将从根本上改变大多数代码的编写方式。是的,我相信 async/await 会比 LINQ 产生更大的影响。理解异步将在短短几年内成为基本必需品。关键字介绍让我们直接开始吧。我将使用一些稍后将阐述的概念——请继续阅读第一部分。异步方法看起来像这样:public ...

.NET(C#) TPL:Task中未觉察异常和TaskScheduler.UnobservedTaskException事件

.NET(C#) TPL:Task中未觉察异常和TaskScheduler.UnobservedTaskException事件

当你在一个Task执行中抛出异常,比如:C#Task.Factory.StartNew(() =>{    throw new Exception();});运行该方法,没有任何异常抛出。事实上此时Task的异常处于未觉察状...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。