博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
委托与事件(续)
阅读量:5261 次
发布时间:2019-06-14

本文共 42115 字,大约阅读时间需要 140 分钟。

本次总结适合初次接触委托事件,或者对委托事件了解但是不能熟练运用的学习者。

再次学习总结委托、事件,上一篇《委托与事件》

01委托

View Code
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace _01委托{    //第一步声明委托    delegate int MyDelegate();    delegate int MyDelegateNumber(int a,int b);    class MyClass    {        public int M1()        {            Console.WriteLine("调用实例方法");            return 0;        }        public static int M2()        {            Console.WriteLine("调用静态方法");            return 0;        }    }    class Add    {        public int NumberAdd(int num1,int num2)        {             return(num1+num2);        }    }    class Program    {        static void Main(string[] args)        {            MyClass myClss = new MyClass();            //实例化委托。非静态方法的调用需要先实例化该类            MyDelegate myDelete1 = new MyDelegate(myClss.M1);            Console.WriteLine("委托一");            myDelete1();            //静态方法的调用直接用 类名.方法名            MyDelegate myDelete2;            myDelete2 = MyClass.M2;//给委托类型的变量赋值            Console.WriteLine("委托二");            myDelete2();            MyDelegate myDelete3 = myDelete1 + myDelete2;            Console.WriteLine("委托三");            myDelete3();            Add myAdd = new Add();            MyDelegateNumber p = new MyDelegateNumber(myAdd.NumberAdd);            Console.WriteLine(p(1,2));            Console.ReadLine();            #region            /*             * 1、委托类似C++中的函数指针,用于通过对方法特征(方法签名)和返回类型的声明,封装了             *    具有相同特征和返回类型的方法,与指针不同的是委托实例独立于它所封装的方法的类。             * 2、委托类型隐含为sealed(密封类),是一个引用类型。             */            #endregion        }    }}

02事件

View Code
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace 事件{    delegate void MyEventHandler(int m,int n);    class MyEvent    {        //声明事件 事件名:active        public event  MyEventHandler active;        //触发事件的方法        public void OnEvent(int m,int n)        {            //判断是否有事件被绑定            if(active!=null)            {                active(m,n);//事件发生。格式:事件名(参数);            }        }    }    class Program    {        static void  Handler(int m,int n)        {            Console.WriteLine("事件发生"+(m+n));        }        static void Main(string[] args)        {                       MyEvent evt = new MyEvent();            //将封装Handler方法的委托添加到active事件的列表中            evt.active += new MyEventHandler(Handler);            //事件的预定就是向委托的调用列表中添加方法。 事件名 += new 委托名(方法名);            //只要事件被触发,委托列表中所预定的方法就会被调用            //调用触发事件的方法            evt.OnEvent(3,4);            Console.ReadLine();            #region//总结一下            /*             * 1、首先声明一个委托,委托的后缀名是EventHandler             * 2、然后在声明一个事件,事件名就是委托名去掉EventHandler的部分。可以在另一个类中声明             * 3、写一个触发事件的方法。首先要判断是否有事件被绑定,然后再触发事件             * 4、写一个方法,用于封装到委托中。             * 5、将封装方法的委托添加到事件的列表中             * 6、最后在Main()方法中调用触发事件的方法。事件名.触发事件的方法名()             * 7、本程序执行的过程:实例化MyEvent类->注册事件->触发事件的方法OnEvent->判断事件是否为空,否:触发事件->执行委托列表中对应的方法            */            #endregion        }    }}

03多播委托

View Code
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace _03多重委托{    //第一步声明一个委托    delegate void AddEventHandler(int m,int n);    class AddNum    {        public void Test1(int m,int n)        {            Console.WriteLine("非静态方法"+(m+n));        }        public static void Test2(int m,int n)        {            Console.WriteLine("静态方法"+(m+n));        }    }    class Program    {        static void Main(string[] args)        {            AddNum myNum = new AddNum();            //第二步实例化委托            AddEventHandler myAdd1 = new AddEventHandler(myNum.Test1);            AddEventHandler myAdd2 = new AddEventHandler(AddNum.Test2);            //调用委托myAdd2 myAdd1            myAdd2(1,1);//封装了myNum.Test1()方法            myAdd1(2,2);//封装了AddNum.Test2()            //多重委托              AddEventHandler myAdd3 = myAdd1 + myAdd2;//(1)封装了 myNum.Test1()和AddNum.Test2()方法            myAdd3(3,3);            AddEventHandler myAdd4 = myAdd3 - myAdd1;//(2)封装了AddNum.Test2()            myAdd4(4,4);            myAdd1 += myAdd2;//(3)封装了 myNum.Test1()和AddNum.Test2()方法            myAdd1(5,5);            myAdd3 -= myAdd2;//(4)封装了myNum.Test1()方法            myAdd3(6,6);            Console.ReadLine();            #region//总结一下-委托的调用与运算            /*             *1、委托实例一旦被创建,将始终引用同一目标对象和方法。这样myAdd1实现了对静态方法      AddNum.Test2()和类的实例化方法myNum.Test1()的封装。             *2、当主程序中调用委托的实例时,实际会调用myNum.Test1()和AddNum.Test2()方法,这样 就实现了对方法的回调。             *3、委托实例所封装的方法的集合称为调用列表             *4、多重委托实质上相当于一个委托实例指向多个方法地址,调用多重委托就会按照调用列表中  的顺序调用多个方法。----实现了C#中的多态             *5、注意在调用委托的时候还应该传入与委托声明时的参数列表匹配的识记参数,当然这些参数  实际传入了被封装的方法,这也就要求我们在声明委托和添加方法的时候格式要对应             *6、委托运算符             *    +:将两个委托实例的调用列表组合起来,产生一个新的委托。如(1)             *    -:从一个委托的调用列表中移除另一个委托的列表项,产生一个新的委托。如(2)             *    +=:将一个委托的调用列表合并到另一个委托的调用列表中,不产生新的委托。如:(3)             *    -=:从一个委托的调用列表中删除另一个委托的调用列表,不产生新的委托。如:(4)             *    初始化一个委托后不能第一次就是用+=,将会出现“使用了未赋值的局部变量”            */            #endregion        }    }}

04委托实现回调

View Code
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace _04委托实现回调{    /*     * 问题描述:对于任意的一组数据,进行选择排序和冒泡排序     *问题解析:给被封装的排序方法提供一个整型数组,通过输出方法将排好序的整型数组输出,至于如何     * 实现排序,委托并不关心。通俗的说就是:给你材料,交给你做,我只要结果。    */    public delegate int[] sortEventHandler(int [] arr);    //建立一个排序类    public class Sort    {        //选择排序        public int[] xuanzeSort(int[] arr)        {             if(arr.Length==0)            {                Console.WriteLine("空数组");            }            else            {                for(int i=0;i
arr[j]) { temp=arr[i]; arr[i]=arr[j]; arr[j] = temp; } } } } return arr; } //冒泡排序 public int[] maopaoSort(int [] arr) { if (arr.Length == 0) { Console.WriteLine("空数组"); } else { for(int i=0;i
arr[j + 1]) { int temp=arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } } return arr; } } class Program { static void Main(string[] args) { int[] myarr = { 12,5,40,8,45,3,1,25,18,10,2}; Console.WriteLine("原数组为"); foreach (int item in myarr) { Console.Write(item+" "); } Console.WriteLine(); Sort st = new Sort(); sortEventHandler mySort1 = new sortEventHandler(st.xuanzeSort); sortEventHandler mySort2 = new sortEventHandler(st.maopaoSort); Console.WriteLine("选择排序"); if (mySort1!= null) { int[] resultArr = mySort1(myarr); foreach (int item in resultArr) { Console.Write(item + " "); } Console.WriteLine(); } else { Console.WriteLine("mySort1的调用列表为空"); } Console.WriteLine("冒泡排序"); if(mySort2!=null) { int[] resultArr = mySort2(myarr); foreach (int item in resultArr) { Console.Write(item+" "); } Console.WriteLine(); } else { Console.WriteLine("mySort2的调用列表为空"); } Console.ReadLine(); } }}

04委托实现回调-改进版

View Code
1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Text;  5   6 namespace _04委托实现回调_改进版  7 {  8     /*  9     * 问题描述:对于任意的一组数据,进行选择排序和冒泡排序 10     *问题解析:给被封装的排序方法提供一个整型数组,通过输出方法将排好序的整型数组输出,至于如何 11     * 实现排序,委托并不关心。通俗的说就是:给你材料,交给你做,我只要结果。 12    */ 13  14     public delegate int[] sortEventHandler(int[] arr); 15     //建立一个排序类 16     public class Sort 17     { 18         //选择排序-直接选择排序 19         #region//直接选择排序思想 20         /* 21          * 选择排序思想:每次遍历数组将剩余数组中的最小值排到本次遍历数组的最前面 22          * 1、两层for循环,第一层用于控制循环遍历的次数,第二层循环用于找到本次循环中的最小值,并将              其排到本次循环体的最前面(每一次第一层循环体中的值在第二层循环体中是保持不变的) 23          * 2、时间复杂度:(arr.Length-1)*arr.Length/2 24          */ 25         #endregion 26         public int[] xuanzeSort(int[] arr) 27         { 28             if (arr.Length == 0) 29             { 30                 Console.WriteLine("空数组"); 31             } 32             else 33             { 34                 for (int i = 0; i < arr.Length - 1; i++) 35                 { 36                     for (int j = i + 1; j < arr.Length; j++) 37                     { 38                         int temp; 39                         //不断的将最小的送到arr[i]的面前,直到循环结束。 40                         if (arr[i] > arr[j]) 41                         { 42                             temp = arr[i]; 43                             arr[i] = arr[j]; 44                             arr[j] = temp; 45                         } 46                     } 47                 } 48  49             } 50             return arr; 51         } 52         //交换排序-冒泡排序 53         #region//冒泡排序思想 54         /* 55          * 冒泡排序思想:每遍历数组一次将数组中剩下的最大的排到本次遍历数组的最后。 56          * 1、每次遍历均是从数组的第一个元素开始的 57          * 2、两层for循环,第一层用来控制遍历的次数,为数组的长度-1;第二层用来找到本次循环中元素的               最大值,并将其排到本次数组的最后。(每一次第一层循环体中的值在第二层循环体中是保持不               变的) 58          * 3、时间复杂度:1+2+...+arr.Length-1=(1+arr.Lngth-1)*(arr.Lngth-1)/2=arr.Length*(arr.Length-1)/2 59          */ 60         #endregion 61         public int[] maopaoSort(int[] arr) 62         { 63             if (arr.Length == 0) 64             { 65                 Console.WriteLine("空数组"); 66             } 67             else 68             { 69                 for (int i = 0; i < arr.Length - 1; i++) 70                 { 71                     for (int j = 0; j < arr.Length - 1 - i; j++) 72                     { 73                         if (arr[j] > arr[j + 1]) 74                         { 75                             int temp = arr[j]; 76                             arr[j] = arr[j + 1]; 77                             arr[j + 1] = temp; 78                         } 79                     } 80                 } 81             } 82             return arr; 83         } 84         //插入排序-直接插入排序 85         #region//插入排序思想 86         /* 87          * 插入排序思想:假设数组中前n-1个都排好序了,现在将数组中的第n个放到前面已排好序的数组中, 88          *               使得这n个数任然是一个排好序的数组。 89          * 1、有一个for循环,先将数组中的前两个数排序,然后再将前三个数排序,...... 90          * 2、每次都是从后向前排序,直到找到合适的位置 91          * 3、时间复杂度:在O(n)到O(n2) 92          */ 93         #endregion 94         public int[] charuSort(int[] arr) 95         { 96             if (arr.Length == 0) 97             { 98                 Console.WriteLine("空数组"); 99             }100             else101             {102                 for (int i = 1; i < arr.Length; i++)103                 {104                     int temp;105                     int j=i;106                     while(j>0&&arr[j-1]>arr[j])107                     {108                         temp=arr[j];109                         arr[j] = arr[j - 1];110                         arr[j - 1] = temp;111                         --j;112                     }113                 }114             }115             return arr;116         }117         #region//希尔排序思想118         /*119          * 希尔排序思想:先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。120          *               先在各组内进行直接插人排序;然后,取第二个增量d2
<…
0)129 {130 for (int i = k; i < arr.Length; i++)131 {132 int t = arr[i];133 int j = i - k;134 while (j >= 0 && t < arr[j])135 {136 arr[j + k] = arr[j];137 j = j - k;138 }139 arr[j + k] = t;140 }141 k /= 2;142 }143 return arr;144 }145 //显示排序后的数组146 public void ShowResult(sortEventHandler se, int[] arr)147 {148 if (se != null)149 {150 int[] resultArr = se(arr);151 foreach (int item in resultArr)152 {153 Console.Write(item + " ");154 }155 Console.WriteLine();156 }157 else158 {159 Console.WriteLine(se + "调用列表为空");160 }161 }162 163 }164 165 class Program166 {167 static void Main(string[] args)168 {169 int[] myarr = { 12, 5, 40, 8, 45, 3, 1, 25, 18, 10, 2 };170 Console.WriteLine("原数组为");171 foreach (int item in myarr)172 {173 Console.Write(item + " ");174 }175 Console.WriteLine();176 177 Sort st = new Sort();178 sortEventHandler mySort1 = new sortEventHandler(st.xuanzeSort);179 sortEventHandler mySort2 = new sortEventHandler(st.maopaoSort);180 sortEventHandler mySort3 = new sortEventHandler(st.charuSort);181 sortEventHandler mySort4 = new sortEventHandler(st.shellSort);182 Console.WriteLine("选择排序");183 st.ShowResult(mySort1, myarr);184 185 Console.WriteLine("冒泡排序");186 st.ShowResult(mySort2, myarr);187 188 Console.WriteLine("快速排序");189 st.ShowResult(mySort3, myarr);190 191 Console.WriteLine("希尔排序");192 st.ShowResult(mySort4,myarr);193 194 Console.ReadLine();195 }196 }197 }

05委托、事件与Observer模式

View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6  7 namespace _05委托_事件与Observer设计模式 8 { 9     public delegate void HeateEventHandler(int temp);10     public class Heater11     {12         //定义一个私有字段13         private int temperature;14         public event HeateEventHandler heate;15         public void HeateOnEvent()16         {17             for (int i = 0; i <= 100;i++ )18             {19                 temperature = i;20                 if(i>96)21                 {22                     if(heate!=null)23                     {24                         heate(temperature);25                         Thread.Sleep(5000);26                     }27                 }28             }29         }30     31     }32     public class Alarm33     {34         public void MakeAlarm(int temp)35         {36             Console.WriteLine("警报:当前水温{0}度",temp);37         }38     }39     public class Display40     {41         public static void ShowDisplay(int temp)42         {43             Console.WriteLine("显示:水快烧开了,当前温度为{0}",temp);44         }45     }46     class Program47     {48         static void Main(string[] args)49         {50             Heater he = new Heater();51             Alarm al = new Alarm();52             he.heate += al.MakeAlarm;53             //给匿名对象注册方法54             //he.heate+=(new Alarm).MakeAlarm;55             he.heate += Display.ShowDisplay;56             he.HeateOnEvent();57             Console.ReadLine();58         }59         #region//总结一下-Observer设计模式60         /*概念:Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变                 时,其他依赖于它的对象会被自动告知并更新。Observer模式是一种松耦合的设计模式。61          * 1、什么是耦合?什么是松耦合?什么是紧耦合?62               解释:耦合就是依赖的程度。松耦合就是依赖程度不强,紧耦合就是依赖程度很强。网上找了个63               形象的解释:假如你去麦当劳前台买可乐, 你可以把你和麦当劳工作人员想象为软件的两层或两               个模块.那么你给服务员5块钱,然后他帮你打一杯可乐,你们之间是松耦合的,你们的接口就是5块               钱,你只要给他钱,就不用管他是怎么拿杯子,从哪打的可乐.但是如果你给他5块钱,然后你要自己              去取杯子,去找可乐机,自己排队, 那么你跟麦当劳就是紧密耦合的.64          * 2、Observer设计模式中主要包括两类对象:Subject(监视对象,包含监视者感兴趣的东西)和                    Observer(监视者,当监视的对象中某个事件发生时,监视者就采取行动)。本例中Heate是监视对              象,Alarm和Dispaly是监视者,感兴趣的东西就是温度,当温度超过某一临界值的时候,监视对               象将监视者感兴趣的东西传给监视者,监视者采取行动。65          * 3、匿名对象:一个临时的对象。没有明确给出名字的对象,只在堆内存中开辟空间,在棧内存中没               有引用地址。66          */67         #endregion68     }69 }

 06为什么要使用事件呢?

View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5  6 namespace _06为什么使用事件 7 { 8     //定义委托 9     public delegate void NumberChangedEventHandler(int count);10     //定义事件的发布者11     public class Publisher12     {13         //声明一个事件14         public event NumberChangedEventHandler NumberChanged;15         //声明一个委托变量16         //(1)public NumberChangedEventHandler NumberChanged;17         //声明触发事件的方法18         public void DoSomething()19         {20             for (int i = 0; i < 23; i++)21             {22                 if (i == 8)23                 {24                     if (NumberChanged != null)25                     {26                         NumberChanged(i);27                     }28                 }29             }30         }31     }32     //定义事件的订阅者33     public class Subscriber34     {35         public void OnNumberChanged(int count)36         {37             Console.WriteLine("事件订阅者:{0}", count);38         }39     }40     class Program41     {42         static void Main(string[] args)43         {44             Subscriber sb = new Subscriber();45             Publisher pb = new Publisher();46             pb.NumberChanged += new NumberChangedEventHandler(sb.OnNumberChanged);47             pb.DoSomething();//事件的本意是当事件发布类中的某个行为触发时,引发事件,也就是说当触发事件的方法满足某个条件时触发事件。事件不应该由客户端触发,而是由事件的发布类的内部触发。这样写使事件的发布类的封装性更好。48             //(1)pb.NumberChanged(100);//定义一个委托变量,这里的NumberChanged不是事件49             Console.ReadLine();50         }51     }52 }

 07让事件只允许一个客户端订阅

View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5  6 namespace _07让事件只允许一个客户端订阅 7 { 8     public delegate string GenneralEventHandler(); 9     public class Publisher10     {11         public event GenneralEventHandler NumberChanged;12         public void Register(GenneralEventHandler method)13         {14             //注意这里:此处注册事件采用的是方法,而不再用+=了15             NumberChanged=method;16         }17         public void UnRegister(GenneralEventHandler method)18         {19             NumberChanged-=method;20         }21         public void DoSomething()22         {23             if(NumberChanged!=null)24             {25                 string rtn=NumberChanged();26                 Console.WriteLine(rtn);27             }28         }29     }30     public class Subscriber131     {32         public string OnNumberChanged()33         {34             Console.WriteLine("subscriber1 invoke");35             return "subscriber1";36         }37     }38     public class Subscriber239     {40         public string OnNumberChanged()41         {42             Console.WriteLine("subscriber2 invoke");43             return "subscriber2";44         }45     }46     class Program47     {48         static void Main(string[] args)49         {50             Publisher pub = new Publisher();51             Subscriber1 sub1 = new Subscriber1();52             Subscriber2 sub2 = new Subscriber2();53             pub.Register(sub1.OnNumberChanged);54             pub.Register(sub2.OnNumberChanged);//输出的是subscriber255             //pub.UnRegister(sub2.OnNumberChanged);//将其注释去掉,输出为空56             pub.DoSomething();57             Console.ReadLine();58         }59     }60 }

08用事件访问器来实现只让一个用户端订阅

View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5  6 namespace _08用事件访问器来实现只让一个用户端订阅 7 { 8     public delegate string GeneralEventHandler(); 9     public class Publisher10     {11         private event GeneralEventHandler numberChanged;12         public event GeneralEventHandler Numberchanged13         {14             add15             {16                 numberChanged = value;17             }18             remove19             {20                 numberChanged -= value;21             }22         }23         public void DoSomething()24         { 25             if(numberChanged!=null)26             {27                 string str = numberChanged();28                 Console.WriteLine(str);29             }30         }31     }32     public class Subscriber133     {34         public string OnNumberChanged()35         {36             Console.WriteLine("subscriber1 invoke");37             return "subscriber1";38         }39     }40     public class Subscriber241     {42         public string OnNumberChanged()43         {44             Console.WriteLine("subscriber2 invoke");45             return "subscriber2";46         }47     }48     class Program49     {50         static void Main(string[] args)51         {52             Publisher pub = new Publisher();53             Subscriber1 sub1 = new Subscriber1();54             Subscriber2 sub2 = new Subscriber2();55             pub.Numberchanged += sub1.OnNumberChanged;56             pub.Numberchanged += sub2.OnNumberChanged;57           //  pub.Numberchanged -= sub2.OnNumberChanged;58             pub.DoSomething();59             Console.ReadLine();60         }61     }62 }

09获得多个返回值与异常处理

View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5  6 namespace _09获得多个返回值与异常处理 7 { 8     public delegate string DemoEventHandler(int num); 9     public class Publisher10     {11         public event DemoEventHandler NumberChanged;12         public List
DoSomething()13 {14 List
strList = new List
();15 if(NumberChanged==null)16 {17 return strList;18 }19 Delegate[] delArray = NumberChanged.GetInvocationList();20 foreach(Delegate del in delArray)21 {22 DemoEventHandler method = (DemoEventHandler)del;//强制向下转换23 strList.Add(method(100));24 }25 return strList;26 }27 }28 public class Subscriber129 {30 public string OnNumberChanged(int num)31 {32 Console.WriteLine("subscriber1 invoke,number:{0}",num);33 return "[Subscriber1 returned]";34 }35 }36 public class Subscriber237 {38 public string OnNumberChanged(int num)39 {40 Console.WriteLine("subscriber2 invoke,number:{0}", num);41 return "[Subscriber2 returned]";42 }43 }44 public class Subscriber345 {46 public string OnNumberChanged(int num)47 {48 Console.WriteLine("subscriber3 invoke,number:{0}", num);49 return "[Subscriber3 returned]";50 }51 }52 class Program53 {54 static void Main(string[] args)55 {56 Publisher pub = new Publisher();57 Subscriber1 sub1 = new Subscriber1();58 Subscriber2 sub2 = new Subscriber2();59 Subscriber3 sub3 = new Subscriber3();60 pub.NumberChanged += new DemoEventHandler(sub1.OnNumberChanged);61 pub.NumberChanged += new DemoEventHandler(sub2.OnNumberChanged);62 pub.NumberChanged += new DemoEventHandler(sub3.OnNumberChanged);63 List
list = pub.DoSomething();64 foreach (string item in list)65 {66 Console.WriteLine(item);67 }68 Console.ReadLine();69 }70 }71 }

10异常处理

View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5  6 namespace _10异常处理 7 { 8     public delegate void MyEventHandler(object sender,EventArgs e); 9     public class Publisher10     {11         public event MyEventHandler MyEvent;12         public void DoSomething()13         {14             if (MyEvent != null)15             {16                 try17                 {18                     MyEvent(this,EventArgs.Empty);19                 }20                 catch(Exception e)21                 {22                     Console.WriteLine("Exception:{0}",e.Message);23                 }24             }25         }26     }27     public class Subscriber128     {29         public void OnEvent(object sender,EventArgs e) 30         {31             Console.WriteLine("Subscriber1 Invoked !");32         }33     }34     public class Subscriber235     {36         public void OnEvent(object sender,EventArgs e)37         {38             throw new Exception("Exception2 Failed");39             //捕获异常,使得程序没有异常结束,但是却影响到了后面的订阅者的执行40         }41     }42     public class Subscriber343     {44         public void OnEvent(object sender,EventArgs e)45         {46             Console.WriteLine("Subscriber3 Invoked!");47         }48     }49     class Program50     {51         static void Main(string [] args)52         {53             Publisher pub = new Publisher();54             Subscriber1 sub1 = new Subscriber1();55             Subscriber2 sub2 = new Subscriber2();56             Subscriber3 sub3 = new Subscriber3();57             pub.MyEvent += new MyEventHandler(sub1.OnEvent);58             pub.MyEvent += new MyEventHandler(sub2.OnEvent);59             pub.MyEvent += new MyEventHandler(sub3.OnEvent);60             pub.DoSomething();61             Console.ReadKey();62         }63     }64  65 }

10异常处理02

View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5  6 namespace _10异常处理02 7 { 8     public delegate void MyEventHandler(object sender, EventArgs e); 9     public class Publisher10     {11         public event MyEventHandler MyEvent;12         public void DoSomething()13         {14             if (MyEvent != null)15             {16                 Delegate[] delArray = MyEvent.GetInvocationList();17                 foreach (Delegate del in delArray)18                 {19                     try20                     {21                         del.DynamicInvoke(this,EventArgs.Empty);22                     }23                     catch(Exception e)24                     {25                         Console.WriteLine("Exception:{0}",e.Message);26                     }27                 }28             }29         }30     }31     public class Subscriber132     {33         public void OnEvent(object sender, EventArgs e)34         {35             Console.WriteLine("Subscriber1 Invoked !");36         }37     }38     public class Subscriber239     {40         public void OnEvent(object sender, EventArgs e)41         {42             throw new Exception("Exception2 Failed");43             //捕获异常,使得程序没有异常结束,但是却影响到了后面的订阅者的执行44         }45     }46     public class Subscriber347     {48         public void OnEvent(object sender, EventArgs e)49         {50             Console.WriteLine("Subscriber3 Invoked!");51         }52     }53     class Program54     {55         static void Main(string[] args)56         {57             Publisher pub = new Publisher();58             Subscriber1 sub1 = new Subscriber1();59             Subscriber2 sub2 = new Subscriber2();60             Subscriber3 sub3 = new Subscriber3();61             pub.MyEvent += new MyEventHandler(sub1.OnEvent);62             pub.MyEvent += new MyEventHandler(sub2.OnEvent);63             pub.MyEvent += new MyEventHandler(sub3.OnEvent);64             pub.DoSomething();65             Console.ReadKey();66         }67     }68 }

10异常处理03

View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5  6 namespace _10异常处理03 7 { 8     public delegate void MyEventHandler(object sender,EventArgs e); 9     public class Publisher10     {11         public event MyEventHandler MyEvent;12         public void DoSomething()13         {14             Publisher.FireEvent(MyEvent,this,EventArgs.Empty);15         }16         public static object[]FireEvent(Delegate del,params object[]args)17         {18             ListobjList=new List();19             if(del!=null)20             {21                 Delegate[]delArray=del.GetInvocationList();22                 foreach(Delegate method in delArray)23                 {24                     try25                     {26                         object obj=method.DynamicInvoke(args);27                         if(obj!=null)28                         {29                             objList.Add(obj);30                         }31                     }32                     catch(Exception e)33                     {34                         Console.WriteLine("Exception:{0}",e.Message);35                         //此处修改写法36                     }37                 }38                 39             }40             return objList.ToArray();41         }42     }43     public class Subscriber144     {45         public void OnEvent(object sender,EventArgs e)46         {47             Console.WriteLine("subscriber1 Invoke !");48         }49     }50     public class Subscriber251     {52         public static void OnEvent(object sender,EventArgs e)53         {54             throw new Exception("Subscriber2 failed !");55         }56     }57     public class Subscriber358     {59         public void OnEvent(object sender,EventArgs e)60         {61             Console.WriteLine("Subscriber3 Invoke !");62         }63     }64     65     class Program66     {67         static void Main(string[] args)68         {69             Publisher pub = new Publisher();70             Subscriber1 sub1 = new Subscriber1();71             Subscriber3 sub3 = new Subscriber3();72 73             pub.MyEvent += new MyEventHandler(sub1.OnEvent);74             pub.MyEvent += new MyEventHandler(Subscriber2.OnEvent);75             pub.MyEvent += new MyEventHandler(sub3.OnEvent);76 77             pub.DoSomething();78 79             Console.ReadLine();80         }81     }82     83 }

11委托中订阅者方法的超时处理

View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6  7 namespace _11委托中订阅者方法的超时处理 8 { 9     public delegate void MyEventHandler(object sender,EventArgs e);10     public class Publisher11     {12         public event MyEventHandler MyEvent;13         public void DoSomething()14         {15             Console.WriteLine("DoSomething invoke !");16             Program.FireEvent(MyEvent,this,EventArgs.Empty);17         }18     }19     public class Subscriber120     {21         public void OnEvent(object sender,EventArgs e)22         {23             Thread.Sleep(TimeSpan.FromSeconds(3));24             Console.WriteLine("Wait for 3 seconds ,subscriber1 invoked !");25         }26         27     }28     public class Subscriber229     {30         public void OnEvent(object sender,EventArgs e)31         {32             Console.WriteLine("Subscriber2 is Invoked !");33         }34     }35     public class Subscriber336     {37         public void OnEvent(object sender,EventArgs e)38         {39             Thread.Sleep(TimeSpan.FromSeconds(2));40             Console.WriteLine("Wait for 2 seconds ,subscriber2 invoked !");41         }42     }43     class Program44     {45         static void Main(string[] args)46         {47             //初始化对象48             Publisher pub = new Publisher();49             Subscriber1 sub1 = new Subscriber1();50             Subscriber2 sub2 = new Subscriber2();51             Subscriber3 sub3 = new Subscriber3();52             //初始化事件53             pub.MyEvent += new MyEventHandler(sub1.OnEvent);54             pub.MyEvent += new MyEventHandler(sub2.OnEvent);55             pub.MyEvent += new MyEventHandler(sub3.OnEvent);56             //调用触发事件的方法57             pub.DoSomething();58             Console.WriteLine("返回控制权");59             Console.ReadLine();60         }61         public static object[] FireEvent(Delegate del,params object[]args)62         {63             List objList = new List();64             if(del!=null)65             {66                 Delegate[] delArray = del.GetInvocationList();67                 foreach(Delegate method in delArray)68                 {69                     try70                     {71                         object obj = method.DynamicInvoke(args);72                         if (obj != null)73                         {74                             objList.Add(obj);75                         }76                     }77                     catch { }78                     }79                 }80             return objList.ToArray();81             }82         }83     #region//总结一下84     /*85      * 1、在依次执行订阅者方法时,当前线程会转去执行方法中的代码,调用方法的客户端会被中断,86      *    只有当方法全部执行完毕之后,控制权才回到客户端手里。87      * 2、事件的发布者并不关心谁订阅了事件,也不关心订阅者的方法有没有返回值,它只需要在事件88      *    发生的瞬间告知订阅者事件已经发生并将相关的参数传给订阅者就可以了,然后继续执行它后89      *    面的代码,而不是等待订阅者完成后再执行后面的代码。90      */91     #endregion92 }

11委托中订阅者方法的超时处理02

View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6  7 namespace _11委托中订阅者方法的超时处理02 8 { 9     //public delegate void MyEventHandler(object sender,EventArgs e);10     public class Publisher11     {12         public event EventHandler MyEvent;13         public void DoSomething()14         {15             Console.WriteLine("DoSomething Invoke !");16             if (MyEvent != null)17             {18                 Delegate[] delArray = MyEvent.GetInvocationList();19                 foreach (Delegate del in delArray)20                 {21                     try22                     {23                         EventHandler method = (EventHandler)del;24                         method.BeginInvoke(null, EventArgs.Empty, null, null);25                         //对于多个订阅者注册的情况,必须使用GetInvocationList()获得所有委托对象,26                         ///然后遍历它们,分别在其上调用BeginInvoke()方法27                     }28                     catch(Exception e)29                     {30                         Console.WriteLine(e.Message);31                     }32 33                 }34             }35         }36     }37     public class Subscriber138     {39         public void OnEvent(object sender, EventArgs e)40         {41             Thread.Sleep(TimeSpan.FromSeconds(3));42             Console.WriteLine("Subscriber1 Invoked ! 延迟3秒");43         }44     }45     public class Subscriber246     {47         public void OnEvent(object sender, EventArgs e)48         {49             throw new Exception("Subscriber2 failed !");50         }51     }52     public class Subscriber353     {54         public void OnEvent(object sender, EventArgs e)55         {56             Thread.Sleep(TimeSpan.FromSeconds(2));57             Console.WriteLine("Subscriber3 Invoked !延迟2秒");58         }59     }60     class Program61     {62         static void Main(string[] args)63         {64             //初始化对象65             Publisher pub = new Publisher();66             Subscriber1 sub1 = new Subscriber1();67             Subscriber2 sub2 = new Subscriber2();68             Subscriber3 sub3 = new Subscriber3();69             //初始化事件70             pub.MyEvent += new EventHandler(sub1.OnEvent);71             pub.MyEvent += new EventHandler(sub2.OnEvent);72             pub.MyEvent += new EventHandler(sub3.OnEvent);73             //调用触发事件的方法74             pub.DoSomething();75             Console.WriteLine("返回控制权");76             Console.WriteLine("press any key to exit");77             Console.ReadLine();78 79             #region80             /*81              * 1、当我们直接调用委托时,实际上是调用了Invoke()方法,它会中断调用它的客户端,然后在82              *    客户端程序上执行所有订阅者的方法,最后将控制权返回客户端83              * 2、客户端所在的线程通常是主线程,而执行订阅者方法的线程来自线程池,属于后台线程,当84              *    主线程结束时,不论后台线程有没有结束,都会退出程序。85              * 3、本次订阅者中一个停留3秒,一个停留两秒,实际上这两个方法是并行执行的,也就是说最长86              *    的是3秒。87              */88             #endregion89         }90     }91 }

12委托和方法的异步调用

View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6  7 namespace _12委托和方法的异步调用 8 { 9     class Program10     {11         static void Main(string[] args)12         {13             Console.WriteLine("Client application started !");14             Thread.CurrentThread.Name = "Main Thread";15 16             Calculator cal = new Calculator();17             int result = cal.Add(2,5);18             Console.WriteLine("Result:{0}",result);19             for (int i = 1; i <= 3;i++ )20             {21                 Thread.Sleep(TimeSpan.FromSeconds(i));22                 Console.WriteLine("{0}:Client executed{1}seconds",Thread.CurrentThread.Name,i);23             }24             Console.ReadLine();25         }26     }27     public class Calculator28     { 29         public int Add(int x,int y)30         {31             if(Thread.CurrentThread.IsThreadPoolThread==true)32             {33                 Thread.CurrentThread.Name = "Pool Thread";34             }35             Console.WriteLine("Method invoked!");36             for (int i = 1; i <= 2;i++ )37             {38                 Thread.Sleep(TimeSpan.FromSeconds(i));39                 Console.WriteLine("{0}:Add executed{1}seconds.",Thread.CurrentThread.Name,i);40             }41             Console.WriteLine("Method complete !");42             return x + y;43         }44     }45 }

12委托和方法的异步调用02

View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6  7 namespace _12委托和方法的异步调用02 8 { 9     public delegate int AddDelegate(int x,int y);10     public class Calculator11     {12         public int Add(int x,int y)13         {14             if(Thread.CurrentThread.IsThreadPoolThread==true)15             {16                 Thread.CurrentThread.Name = "线程池";17             }18             //延缓两秒钟19             for (int i = 1; i <= 2;i++ )20             {21                 Thread.Sleep(TimeSpan.FromSeconds(i));22                 Console.WriteLine("{0}:延缓{1}秒",Thread.CurrentThread.Name,i);23             }24             Console.WriteLine("方法执行完毕");25             return x + y;26         }27     }28     class Program29     {30         static void Main(string[] args)31         {32             Console.WriteLine("客户端应用程序开始执行");33             Thread.CurrentThread.Name = "主线程";34 35             Calculator cal = new Calculator();36             AddDelegate del = new AddDelegate(cal.Add);37             IAsyncResult asr=del.BeginInvoke(2,3,null,null);38             //模拟3秒钟39             for (int i = 1; i <= 3;i++ )40             {41                 Thread.Sleep(TimeSpan.FromSeconds(i));42                 Console.WriteLine("{0}:客户端线程停留{1}",Thread.CurrentThread.Name,i);43             }44             int result = del.EndInvoke(asr);45             Console.WriteLine("结果:{0}",result);46             Console.WriteLine("结束");47 48             Console.ReadLine();49         }50     }51 }

 委托的分析:

参考文章地址:http://www.cnblogs.com/Alpha-Fly/archive/2012/04/04/2431880.html

委托的定义: public delegate 返回类型 FuncDelegate(参数列表);

这里是一个类型,可以定义一个FuncDelegate类型的变量
而定义的这个变量就可以存放与这个委托具有相同返回值类型、相同参数类型的方法名

 委托是一种类型安全的函数回调机制,它不仅能够调用实例方法,也能够调用静态方法,并且具备按顺序执行多个方法的能力。

委托与函数指针的区别:

函数指针是面向过程的,它指向内存空间的一片地址,再由地址找到函数的代码块,去执行代码。

委托是面向对象的,是一个类(用Reflector查看,是new出来的),实际上是将方法名作为参数传递进来进行了封装,在调用的时候直接调用这个方法。

 

委托本质是一个类。委托内部(在其父类MulticastDelegate)有一个集合(invocationList)来维护方法列表,执行的时候是调用方法列表中的方法,即用委托名.Invoke();同时有一个invocationCount变量记录方法列表中方法的个数,而对于实例,是将其存放在基类Delegate的Target中的。(如下例的name字段)

下图是对委托原理的大致总结:

 

要想了解具体的实现步骤,请结合Reflector查看!

 

 

异步委托:说白了就是另外开启一个线程来执行操作

实现方式一:没有回调函数

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace 异步委托{    //声明一个委托    public delegate int DelAdd(int x,int y);    class Program    {        static void Main(string[] args)        {            //打印当前主线程            Console.WriteLine("当前主线程是:{0}",Thread.CurrentThread.ManagedThreadId);            //实例化委托            DelAdd delAdd = new DelAdd(MyAdd);            var asResult = delAdd.BeginInvoke(1, 2, null, null);            int num = 1;            //询问异步委托执行完了没有            while (!asResult.IsCompleted)            {                //主线程可以执行其他操作                Console.WriteLine("主线程还在执行"+num);                num++;            }            int result = delAdd.EndInvoke(asResult);            Console.WriteLine("我执行完了");            Console.ReadKey();        }        //定义满足委托定义的方法        static int MyAdd(int x,int y)        {            //打印当前线程            Console.WriteLine("当前线程标识符是:"+Thread.CurrentThread.ManagedThreadId);            return x+y;        }    }}

实现方式二:有回调函数

using System;using System.Collections.Generic;using System.Linq;using System.Runtime.Remoting.Messaging;using System.Text;using System.Threading;namespace 异步委托02{    public delegate int DelAdd(int x,int y);    class Program    {        static void Main(string[] args)        {            //这个程序中采用回调函数来帮助实现异步委托            //打印当前线程的标识符            Console.WriteLine("当前线程的标识符"+Thread.CurrentThread.ManagedThreadId);            DelAdd delAdd = new DelAdd(MyAdd);            delAdd.BeginInvoke(1, 2, new AsyncCallback(MyAsyncCallback), 12);            Console.WriteLine("我结束了");            Console.ReadKey();        }        //编写一个符合委托的方法        static int MyAdd(int x, int y)        {            Console.WriteLine("1当前线程标识符是"+Thread.CurrentThread.ManagedThreadId);            return x + y;        }        static void MyAsyncCallback(IAsyncResult result)        {            Console.WriteLine("2当前线程标识符是" + Thread.CurrentThread.ManagedThreadId);            //将接口类型转换成实例类型            AsyncResult aResult = (AsyncResult)result;            //将实例类型转换成委托类型            DelAdd del=(DelAdd)aResult.AsyncDelegate;            //获取执行结果            int addResult = del.EndInvoke(result);            //获取随BeginInvoke传入的参数            int state = (int)aResult.AsyncState;            Console.WriteLine("异步完成回调方法执行的结果"+state);        }    }}

 

转载于:https://www.cnblogs.com/chenyongblog/archive/2013/04/25/3043605.html

你可能感兴趣的文章
发布.NET MVC网站 到Azure
查看>>
【Codeforces 923A】Primal Sport
查看>>
【“玲珑杯”ACM比赛 Round #20 H】康娜的数学课
查看>>
【74.00%】【codeforces 747A】Display Size
查看>>
webservice之XFire的使用(java调用java)
查看>>
Try::Tiny Perl 异常的处理
查看>>
JqueryTips小实验,浏览器滚动条不限制
查看>>
步步为营-46-参数
查看>>
MongoDB学习(1)—在Windows系统中安装MongoDB
查看>>
iOS开发之cell多按钮
查看>>
Poj 1008
查看>>
C#.NET 获取拨号连接 宽带连接
查看>>
.net基础收集
查看>>
程序员的热血与梦想
查看>>
HTC G14解锁S-OFF 获取ROOT权限
查看>>
理解git对象
查看>>
[LeetCode] Merge Intervals
查看>>
【翻译自mos文章】当点击完 finishbutton后,dbca 或者dbua hang住
查看>>
Apache配置反向代理、负载均衡和集群(mod_proxy方式)
查看>>
Linux编程简介——gcc
查看>>