区分异步和多线程应用场景(IO操作包括获取网络数据用异步,大量耗时的计算用线程)
2012-08-17 10:59
423 查看
我们会了解到异步的实质、任务的实质,以及为什么有了任务还需要一个并行类(Parallel)等问题。同时,本章内容还会告诉我们如何优雅地控制线程,并且处理任务和并行中的异常。本节为大家介绍建议71:区分异步和多线程应用场景。
第6章 异步、多线程、任务和并行在软件开发过程中,有一个领域的工作处理起来几乎总是最棘手的,这就是多线程编码。由多线程带来的传值、取值、资源同步、线程暂停、取消等操作会困扰每一个尝试编写此类代码的程序员。微软在这方面也做了巨大的努力,现在FCL中有了非常丰富的API可供选择,以便编写多线程代码。但这也带来了一个新问题:选择太多了,该选择什么样的类和方法呢?本章将通过具体的实例,让我们熟悉异步、多线程、任务和并行。我们会了解到异步的实质、任务的实质,以及为什么有了任务还需要一个并行类(Parallel)等问题。同时,本章内容还会告诉我们如何优雅地控制线程,并且处理任务和并行中的异常。
多线程编码是所有开发人员前进途中的一个坎,现在,该是尝试克服它的时候了。
建议71:区分异步和多线程应用场景
初学者有时候会将异步和多线程混为一谈。如果对它们之间的区别不是很清楚,很容易写出下面这样的代码:
是的,上面的程序解决了界面阻滞的问题,但是,它高效吗?答案是:不。要理解这一点,需要从“IO操作的DMA(Direct Memory
Access)模式”开始讲起。DMA即直接内存访问,是一种不经过CPU而直接进行内存数据存储的数据交换模式。通过DMA的数据交换几乎可以不损耗CPU的资源。在硬件中,硬盘、网卡、声卡、显卡等都有DMA功能。CLR所提供的异步编程模型就是让我们充分利用硬件的DMA功能来释放CPU的压力。
了解这一点,再来重新审视本建议开头的这个例子。其开头部分的示例代码可以用图6-1来阐述。
为了获取网页,CLR新起了一个工作线程,然后在读取网页的整个过程中,该工作线程始终被阻滞,直到获取网页完毕为止。在整个过程中,工作线程被占用着,这意味着系统的资源始终被消耗着、等待着。
如果我们修改一下代码,使用异步模式去实现,代码如下所示:
经过修改的示例采用了异步模式,它使用线程池进行管理。新起异步操作后,CLR会将工作丢给线程池中的某个工作线程来完成。当开始I/O操作的时候,异步会将工作线程还给线程池,这时候就相当于获取网页的这个工作不会再占用任何CPU资源了。直到异步完成,即获取网页完毕,异步才会通过回调的方式通知线程池,让CLR响应异步完毕。可见,异步模式借助于线程池,极大地节约了CPU的资源。
明白了异步和多线程的区别后,我们来确定两者的应用场景:
计算密集型工作,采用多线程。
IO密集型工作,采用异步机制。
转自:http://it.anhuinews.com/762352/161940365229.shtml
第6章 异步、多线程、任务和并行在软件开发过程中,有一个领域的工作处理起来几乎总是最棘手的,这就是多线程编码。由多线程带来的传值、取值、资源同步、线程暂停、取消等操作会困扰每一个尝试编写此类代码的程序员。微软在这方面也做了巨大的努力,现在FCL中有了非常丰富的API可供选择,以便编写多线程代码。但这也带来了一个新问题:选择太多了,该选择什么样的类和方法呢?本章将通过具体的实例,让我们熟悉异步、多线程、任务和并行。我们会了解到异步的实质、任务的实质,以及为什么有了任务还需要一个并行类(Parallel)等问题。同时,本章内容还会告诉我们如何优雅地控制线程,并且处理任务和并行中的异常。
多线程编码是所有开发人员前进途中的一个坎,现在,该是尝试克服它的时候了。
建议71:区分异步和多线程应用场景
初学者有时候会将异步和多线程混为一谈。如果对它们之间的区别不是很清楚,很容易写出下面这样的代码:
private void buttonGetPage_Click(object sender, EventArgs e) { Thread t = new Thread(() => { var request = HttpWebRequest.Create("http://www.cnblogs.com/luminji"); var response = request.GetResponse(); var stream = response.GetResponseStream(); using (StreamReader reader = new StreamReader(stream)) { var content = reader.ReadLine(); textBoxPage.Text = content; } }); t.Start(); }上面的代码模拟了在一个Winform窗体程序中,单击Button获取某个网页的内容并显示出来。可以预见,如果该网页的内容很多,或者当前的网络状况不太好,获取网页的过程会持续较长时间。于是,我们可能会想到用新起工作线程的方法来完成这项工作,这样在等待网页内容返回的过程中Winform界面就不会被阻滞了。
是的,上面的程序解决了界面阻滞的问题,但是,它高效吗?答案是:不。要理解这一点,需要从“IO操作的DMA(Direct Memory
Access)模式”开始讲起。DMA即直接内存访问,是一种不经过CPU而直接进行内存数据存储的数据交换模式。通过DMA的数据交换几乎可以不损耗CPU的资源。在硬件中,硬盘、网卡、声卡、显卡等都有DMA功能。CLR所提供的异步编程模型就是让我们充分利用硬件的DMA功能来释放CPU的压力。
了解这一点,再来重新审视本建议开头的这个例子。其开头部分的示例代码可以用图6-1来阐述。
图6-1 多线程工作的示意图 |
如果我们修改一下代码,使用异步模式去实现,代码如下所示:
private void buttonGetPage_Click(object sender, EventArgs e) { var request = HttpWebRequest.Create("http://www.sina.com.cn"); request.BeginGetResponse(this.AsyncCallbackImpl, request); } public void AsyncCallbackImpl(IAsyncResult ar) { WebRequest request = ar.AsyncState as WebRequest; var response = request.EndGetResponse(ar); var stream = response.GetResponseStream(); using (StreamReader reader = new StreamReader(stream)) { var content = reader.ReadLine(); textBoxPage.Text = content; } }以上代码的工作机制可以用图6-2来描述
图6-2 异步工作的机制 |
明白了异步和多线程的区别后,我们来确定两者的应用场景:
计算密集型工作,采用多线程。
IO密集型工作,采用异步机制。
转自:http://it.anhuinews.com/762352/161940365229.shtml
相关文章推荐
- 黑马程序员--读写字节数组,随机读写流,集合IO的思维导图,多线程部分,单例设计模式,线程和进程的概念,Java中的线程的创建方式,线程的随机性,线程的状态图,多线程操作共享数据的安全性,死锁
- 编写高质量代码改善C#程序的157个建议——建议71:区分异步和多线程应用场景
- Android使用AsyncTask异步线程网络通信获取数据(get json)
- 建议71:区分异步和多线程应用场景
- android 线程实现异步网络数据获取
- .net 读书笔记 区分异步和多线程应用场景
- 建议71:区分异步和多线程应用场景
- 多线程操作数据拷贝要加线程锁
- Android应用中使用AsyncHttpClient来异步网络数据
- 利用线程和异步线程AsyncTask获取网络图片
- 多线程并发库高级应用 之 线程范围内共享数据
- 网络编程_post_异步-代理_获取网络数据
- iOS 开发 多线程详解之NSThread异步线程下载网络图片
- 用 get 同步/异步 方式获取网络数据并输出
- 实现iOS中发起异步网络请求,需要等待其返回的数据才能执行下一步操作
- Android操作sqlite导入大量数据耗时的解决方法
- Android应用开发之获取网络数据
- Java多线程总结(4)— 线程范围内数据操作的隔离及ThreadLocal类
- 五种IO 模式——阻塞(默认IO模式),非阻塞(常用语管道),IO多路复用(IO多路复用的应用场景),信号IO,异步IO
- 触发器应用场景一: 根据业务逻辑限制某些操作__触发器应用场景二: 校验数据