ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

三种异步编程模型

2019-12-16 14:04:01  阅读:328  来源: 互联网

标签:异步 MessageBox TPL Show buffer 编程 三种 async await


Net 中很多的类接口设计的时候都考虑了多线程问题,简化了多线程程序的开发。 不用自己去写 WaitHandler 等这些底层的代码。由于历史的发展,这些类的接口设计有着三种不同的风格: EAP(*)、
APM(*)和 TPL。目前重点用 TPL。

 

EAP


EAP 是 Event-based Asynchronous Pattern( 基于事件的异步模型) 的简写, 类似于 Ajax 中的XmlHttpRequest, send 之后并不是处理完成了,而是在 onreadystatechange 事件中再通知处理完成。

 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }    

        private void button1_Click(object sender, EventArgs e)
        {
         
            WebClient client = new WebClient();
            client.DownloadStringCompleted += Client_DownloadStringCompleted;
            client.DownloadStringAsync(new Uri("http://www.baidu.com")); ;

        }

        private void Client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            MessageBox.Show(e.Result);
        }
    }

优点是简单,缺点是当实现复杂的业务的时候很麻烦,比如下载 A 成功后再下载 b,如果下载 b成功再下载 c,否则就下载 d。
EAP 的类的特点是:一个异步方法配一个***Completed 事件。 .Net 中基于 EAP 的类比较少。也有更好的替代品,因此了解即可。

 

AMP


APM(Asynchronous Programming Model)是.Net 旧版本中广泛使用的异步编程模型。使用了 APM的异步方法会返回一个 IAsyncResult 对象, 这个对象有一个重要的属性 AsyncWaitHandle, 他是一个
用来等待异步任务执行结束的一个同步信号。

 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            FileStream fs = File.OpenRead("d:/1.txt");
            byte[] buffer = new byte[16];
            IAsyncResult aResult = fs.BeginRead(buffer, 0, buffer.Length, null, null);
            aResult.AsyncWaitHandle.WaitOne();//等待任务执行结束
            MessageBox.Show(Encoding.UTF8.GetString(buffer));
            fs.EndRead(aResult);
        }
    }

如果不加 aResult.AsyncWaitHandle.WaitOne() 那么很有可能打印出空白,因为 BeginRead只是“开始读取”。调用完成一般要调用 EndXXX 来回收资源。APM 的特点是:方法名字以 BeginXXX 开头,返回类型为 IAsyncResult, 调用结束后需要EndXXX。
.Net 中有如下的常用类支持 APM: Stream、 SqlCommand、 Socket 等。
APM 还是太复杂,了解即可。

 

TPL


TPL(Task Parallel Library)是.Net 4.0 之后带来的新特性,更简洁,更方便。现在在.Net平台下已经大面积使用。

  private void button1_Click(object sender, EventArgs e)
        {
            FileStream fs = File.OpenRead("d:/1.txt");
            byte[] buffer = new byte[16];
            Task<int> task = fs.ReadAsync(buffer, 0, buffer.Length);
            task.Wait();
            MessageBox.Show("读取了" + task.Result + "个字节");
            MessageBox.Show(Encoding.UTF8.GetString(buffer));
        }

使用async和awit关键字

 private async void button2_Click(object sender, EventArgs e)
        {
            FileStream fs = File.OpenRead("d:/1.txt");
            byte[] buffer = new byte[16];
            int len = await fs.ReadAsync(buffer, 0, buffer.Length);
            MessageBox.Show("读取了" + len + "个字节");
            MessageBox.Show(Encoding.UTF8.GetString(buffer));
        }

注意方法中如果有 await,则方法必须标记为 async,不是所有方法都可以被轻松的标记为 async。 WinForm 中的事件处理方法都可以标记为 async、 MVC 中的 Action 方法也可以标记为 async、控制台的 Main 方法不能标记为 async。
TPL 的特点是:方法都以 XXXAsync 结尾,返回值类型是泛型的 Task<T>。
TPL 让我们可以用线性的方式去编写异步程序,不再需要像 EAP 中那样搞一堆回调、逻辑跳来跳去了。 await 现在已经被 JavaScript 借鉴走了!

 


用 await 实现“先下载 A,如果下载的内容长度大于 100 则下载 B,否则下载 C”就很容易了
再看看 WebClient 的 TPL 用法:

private async void button3_Click(object sender, EventArgs e)
        {
            var wc = new WebClient();
            string html = await wc.DownloadStringTaskAsync("http://www.baidu.com");//不要丢了 await
            MessageBox.Show(html);
            //上面的代码并不是完全等价于
            WebClient wc1 = new WebClient();
            var task = wc1.DownloadStringTaskAsync("http://www.baidu.com");
            task.Wait();
            MessageBox.Show(task.Result);

            //  因为如果按照上面的写法,会卡死 UI 线程
            //而 await 则 不 会 。。。 好 像 不 是 ? ? ? 那 只 是 因 为 把 html 这 么 长 的 字 符 串
            //MessageBox.Show 很慢, MessageBox.Show(html.Substring(10)); 就证明了这一点


            // Task<T> 中的 T 是什么类型每个方法都不一样,要看文档。
            //WebClient、 Stream、 Socket 等这些“历史悠久”的类都同时提供了 APM、 TPL 风格的
            //API,甚至有的还提供了 EAP 风格的 API。尽可能使用 TPL 风格的
        }

编写异步方法

返回值为 Task<T>,潜规则(不要求)是方法名字以 Async 结尾:

 static Task<string> F2Async()
        {
            return Task.Run(() =>
            {
                System.Threading.Thread.Sleep(2000);
                return "F2";
            });
        }

调用

 private async void button4_Click(object sender, EventArgs e)
        {
            string s = await F2Async();
            MessageBox.Show(s);

        }

 

标签:异步,MessageBox,TPL,Show,buffer,编程,三种,async,await
来源: https://www.cnblogs.com/Jenkin/p/12048748.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有