C#多线程和异步(三)——一些异步编程模式

一、任务并行库

  任务并行库(Task Parellel Library)是BCL中的一个类库,极大地简化了并行编程,这里以Parallel.For和Parallel.ForEach为例。在C#中for/foreach循环使用十分普遍,如果迭代不依赖与上次迭代的结果时,把迭代放在 不同的处理器上并行处理 将很大地提高运行效率,Parallel.For和Parallel.ForEach就是为这个目的而设计的。

一个栗子:

 1      static void Main(string[] args)
 2         {
 3             //Parallel.For  计算0到10的平方
 4             Parallel.For(1, 6, i =>
 5             {
 6                 Console.WriteLine("The square of {0} is {1}", i, i * i);
 7             });
 8
 9             //Parallel.ForEach 计算每个字符串的长度
10             string[] strs = { "We", "hold", "these", "truths" };
11             Parallel.ForEach(strs, i => Console.WriteLine("{0} has {1} letters",i,i.Length));
12             Console.ReadKey();
13         }

运行结果:

二、计时器(Timer)

  计时器提供了一种 定期重复运行异步方法 的方式,当计时器到期后,系统从线程池中的线程上开启一个回调方法,把state作为参数,并开始运行。

Timer最常用的构造函数如下:

Timer(TimeCallback callback,object state,uint dueTime, uint period)

callback是一个返回值为void的委托,state为传入callback的参数,dueTime为第一次调用前的时间,period为两次调用的时间间隔

一个栗子:

 1  class Program
 2     {
 3         int count = 0;
 4         void Run(object state)
 5         {
 6             Console.WriteLine("{0},已经调用了{1}次了", state, ++count);
 7         }
 8         static void Main(string[] args)
 9         {
10             Program p = new Program();
11             //2000毫秒后开始调用,每次间隔1000毫秒
12             Timer timer = new Timer(p.Run, "hello", 2000, 1000);
13             Console.WriteLine("Timer start");
14
15             Console.ReadLine();
16         }
17     }

执行结果:

三、委托执行异步

  使用委托执行异步,使用的是引用方法,如果一个委托对象在调用列表中只有一个方法(这个方法就是引用方法),它就可以异步执行这个方法。委托类有两个方法BeginIvoke和EndInvoke。

   BeginInvoke :执行BeginInvoke方法时,会线程池中获取一个独立线程来执行引用方法,并立即返回到原始线程一个实现IAsyncResult接口的对象的引用(该对象包含了线程池中线程运行异步方法的状态),原始线程继续执行,而引用方法在线程池的线程中并行执行。

   EndInvoke  : 获取异步方法调用返回的值,并释放资源,该方法把异步方法的返回值作为自己的返回值。

委托执行异步编程的3种模式:

  等待一直到完成(wait-until-done):在发起了异步方法,原始线程执行到EndInvoke时就中断并且等异步方法完成完成后再继续。

  轮询(polling):原始线程定期检查发起的线程是否完成(通过IAsyncResult.IsCompleted属性判断),如果没有则继续进行原始线程中的任务。

  回调(callback):原始线程一直执行,无需等待或检查发起的线程是否完成,在发起的线程中的引用方法完成之后,发起线程会调用回调方法,由回调方法在调用EndInvoke之前处理异步方法的结果。

①等待一直到完成模式

  原始线程执行到EndInvoke,如果异步任务没有完成就一直等待

 1     delegate int MyDel(int first,int second);//委托声明
 2     class Program
 3     {
 4         static int Sum(int x, int y)
 5         {
 6             Thread.Sleep(1000);
 7             return x + y;
 8         }
 9         static void Main(string[] args)
10         {
11             MyDel del = Sum;
12             //调用异步操作(第三个参数是回调函数,第四个参数是额外的值)
13             IAsyncResult iar = del.BeginInvoke(3, 5, null, null);
14
15             //doSomehing...
16
17             //☆☆☆  执行EndInvoke,如果引用方法Sum没有执行完成,主线程就等待其完成
18             int result = del.EndInvoke(iar);
19             Console.WriteLine(result);
20         }
21     }

②轮询模式

  定期查询任务是否完成:

 1     delegate int MyDel(int first,int second);//委托声明
 2     class Program
 3     {
 4         static int Sum(int x, int y)
 5         {
 6             Thread.Sleep(1000);
 7             return x + y;
 8         }
 9         static void Main(string[] args)
10         {
11             MyDel del = Sum;
12             IAsyncResult iar = del.BeginInvoke(3, 5, null, null);
13
14             //☆☆☆ 通过iar.IsCompleted定期查询完成状态
15             while (!iar.IsCompleted)//IsCompleted表示调用的异步操作是否完成
16             {
17                 //doSomething
18                 Thread.Sleep(300);
19                 Console.WriteLine("no done");
20             }
21             int result = del.EndInvoke(iar);
22             Console.WriteLine(result);
23             Console.ReadKey();
24         }
25     }

③回调模式

原始线程执行委托的BeginInvoke后就不管新线程的事了,委托中的引用方法执行完成后,在回调函数中获取结果并处理,执行委托的EndInvoke方法

 1     delegate int MyDel(int first,int second);//委托声明
 2     class Program
 3     {
 4         static int Sum(int x, int y)
 5         {
 6             Thread.Sleep(1000);
 7             return x + y;
 8         }
 9
10         //回调方法的签名和返回值类型必须和AsyncCallBack委托类型一致
11         //输入参数为IAsyncResult,返回值是Void类型
12        static void CallWhenDone(IAsyncResult iar){
13            AsyncResult ar = (AsyncResult)iar;
14            MyDel del = (MyDel)ar.AsyncDelegate;
15            int result = del.EndInvoke(iar);
16            Console.WriteLine("回调函数执行EndInvoke");
17            Console.WriteLine("result:{0}", result);
18            Console.WriteLine("回调函数完成");
19         }
20
21         static void Main(string[] args)
22         {
23             MyDel del = Sum;
24             //执行BeginInvoke方法后原始线程就不用管了,在自定义的回调函数(CallWhenDone)中执行EndInvoke方法
25             IAsyncResult iar = del.BeginInvoke(3, 5, CallWhenDone, null);
26             Console.WriteLine("开启新线程,异步任务完成后执行回调函数");
27             //doSomething
28             Console.WriteLine("回调执行不阻塞原始线程");
29             Console.ReadKey();
30         }
31     }

执行结果:

还有一些其他的异步编程模式如BackgroundWorker这里不再细说了。

  

原文地址:https://www.cnblogs.com/wyy1234/p/9178647.html

时间: 2024-08-02 17:49:01

C#多线程和异步(三)——一些异步编程模式的相关文章

多线程:多线程设计模式(三):Master-Worker模式

Master-Worker模式是常用的并行模式之一,它的核心思想是,系统有两个进程协作工作:Master进程,负责接收和分配任务:Worker进程,负责处理子任务.当Worker进程将子任务处理完成后,结果返回给Master进程,由Master进程做归纳汇总,最后得到最终的结果. 一.什么是Master-Worker模式: 该模式的结构图: 结构图: Worker:用于实际处理一个任务: Master:任务的分配和最终结果的合成: Main:启动程序,调度开启Master. 二.代码实现: 下面

iOS 网络编程模式总结

IOS 可以采用三类api 接口进行网络编程,根据抽象层次从低到高分别为socket方式.stream方式.url 方式. 一 .socket 方式 IOS 提供的socket 方式的网络编程接口为CFSocket.CFSocket是BSD sockets的抽象和封装,CFSocket提供BSD sockets几乎所有的功能,并与run loop集成,用来实现多线程网络编程和网络事件监听.基于 CFSocket可以实现各种类型的 socket编程,包括stream-based 的sockets(

[.net 多线程]异步编程模式

从.NET 4.5开始,支持的三种异步编程模式: 基于事件的异步编程设计模式 (EAP,Event-based Asynchronous Pattern) 异步编程模型(APM,Asynchronous Programming Model) 基于任务的编程模型(TAP,Task-based Asynchronous Pattern) 基于任务的异步模式 (TAP) 是基于 System.Threading.Tasks 命名空间的 Task 和 Task<TResult>,用于表示任意异步操作.

C#中的异步调用及异步设计模式(三)——基于事件的异步模式

四.基于事件的异步模式(设计层面) 基于事件的C#异步编程模式是比IAsyncResult模式更高级的一种异步编程模式,也被用在更多的场合.该异步模式具有以下优点: ·                  “在后台”执行耗时任务(例如下载和数据库操作),但不会中断您的应用程序. ·                  同时执行多个操作,每个操作完成时都会接到通知(在通知中可以区分是完成了哪个操作). ·                  等待资源变得可用,但不会停止(“挂起”)您的应用程序. ·  

多线程实现简单的事件异步处理框架

老实说,多线程在web开发里面非常常见,很多web容器本身就支持多线程,所以很多时候我们在进行web开发的时候并不需要考虑多线程相关的负责问题,而只需要实现相关的业务功能即可.所以,可以概括地讲,很多时候的web开发,并没有多线程方面的考虑,因为web应用本身就是在多线程基础上的了. 但是,有些时候为了提高程序性能,在用户的一个请求中中如果包含过多的业务操作或者包含耗时比较长的业务操作,我们就需要考虑使用异步的方式来提高程序响应的速度了.这篇博客简单介绍了在java中如何使用多线程实现一个简单的

异步编程模式

.NET Framework 提供了三种异步操作模式: 异步编程模型(APM) 模式(也叫 IAsyncResult 模式),这些异步操作需要 Begin和End 方法(例如用于写操作的 BeginWrite 和EndWrite ).这种模式已经不推荐在新项目中使用.更多信息参考: 异步编程模型 (APM). 基于事件的异步模式 (EAP),这种模式的方法带有Async 后辍,并需要一个或多个事件,事件处理的委托类型以及 EventArg-驱动的类型.EAP 自 .NET Framework 2

.NET &ldquo;底层&rdquo;异步编程模式&mdash;&mdash;异步编程模型

本文内容 异步编程类型 环境 异步编程模型(APM) 参考资料 首先澄清,异步编程模式(Asynchronous Programming Patterns)与异步编程模型(Asynchronous Programming Model,APM),它们的中文翻译只差一个字,英文名称差在最后一个单词,看英文一个是 Pattern,一个是 Model.Model 比 Pattern 更具体.前者是一个统称,比后者含义要广,前者包含三个模型,而 APM 只是它其中一个而已. 个人理解,异步编程模型(APM

【转】 VC中TCP实现 异步套接字编程的原理+代码

所谓的异步套接字编程就是  调用了 如下函数   WSAAsyncSelect   设置了 套接字的状态为异步,有关函数我会在下面详细介绍... 异步套接字解决了 套接字编程过程中的堵塞问题 ...... 什么是堵塞?请看下面  你可能有过这样的体会  在  VC编写基于界面的网路程序时候  ,调用 recv recvfrom   accept  等函数的时候 整个程序的主线程进入堵塞状态直到 有连接或者信息的到来.  我们可以利用多线程的方法解决主线程堵塞的问题,但是我们如果一个程序需要多个套

基于事件的异步编程模式(EAP)

一.引言 在上一个专题中为大家介绍了.NET 1.0中提出来的异步编程模式--APM,虽然APM为我们实现异步编程提供了一定的支持,同时它也存在着一些明显的问题--不支持对异步操作的取消和没有提供对进度报告的功能,对于有界面的应用程序来说,进度报告和取消操作的支持也是必不可少的,既然存在这样的问题,微软当然也应该提供给我们解决问题的方案了,所以微软在.NET 2.0的时候就为我们提供了一个新的异步编程模型,也就是我这个专题中介绍的基于事件的异步编程模型--EAP. 二.介绍 实现了基于事件的异步