• C# 委托与事件


     委托,相当于函数指针,是引用类型,有多播功能

    委托的声明    public delegate double MyDelegate ( double x );

          委托就是函数原型,起一个名字。

    委托的实例化   MyDelegated d2 = new MyDelegate( obj.myMethod );

          委托变量,是某个对象的方法或者某个类的方法

    委托的调用    委托变量名(参数列表 )    d2(8.9) 

    委托的合并    多播MultiCastDelegate

      一个委托实例中可以“包含”多个函数

      调用委托,就是调用其中多个函数

      多个函数间的先后顺序是没有意义的

      返回值也就没有太多意义

    运算符 + - += -=

      动态地增减其中的函数

      提高了程序的灵活性

     1 using System;
     2 
     3 public delegate void Action();
     4 
     5 class Program
     6 {
     7     public static void Main(string[] args)
     8     {
     9         //实例化对象
    10         Mom mom = new Mom();
    11         Dad dad = new Dad();
    12         Child child = new Child();
    13         
    14         //将爸爸和孩子的Eat方法注册到妈妈的Eat事件
    15         //订阅妈妈开饭的消息
    16         mom.Eat += dad.Eat;
    17         mom.Eat += child.Eat;
    18         
    19         //调用妈妈的Cook事件
    20         mom.Cook();
    21         
    22         Console.Write("Press any key to continue . . . ");
    23         Console.ReadKey(true);
    24     }
    25 }
    26 
    27 public class Mom
    28 {
    29     //定义Eat事件,用于发布吃饭消息
    30     public event Action Eat;
    31     
    32     public void Cook()
    33     {
    34         Console.WriteLine("妈妈 : 饭好了");
    35         //饭好了,发布吃饭消息!!!
    36         Eat();
    37         //Eat?.Invoke();
    38         //(Eat).Invoke();
    39     }
    40 }
    41 
    42 public class Dad
    43 {
    44     public void Eat()
    45     {
    46         //爸爸去吃饭
    47         Console.WriteLine("爸爸 : 吃饭了。");
    48     }
    49 }
    50 
    51 public class Child
    52 {
    53     public void Eat()
    54     {
    55         //熊孩子LOL呢,打完再吃
    56         Console.WriteLine("孩子 : 打完这局再吃。");
    57     }
    58 }
    委托与事件代码

    事件,相当于回调函数,是一种消息机制,事件源调用事件,别的类注册事件,事件的类型是一个委托

    事件实质上就是一个委托,是受限制的委托,只能在类内部定义以类对象调用类方法的形式,激发

    事件的声明 

      public event 委托名 事件名;

    事件的注册与移除     

      事件名 += 或 -=       

      在事件所在类的外面,只能用以上两个运算符

    事件的发生(激发)     

      事件名(参数列表)     

      相当于回调所注册的函数

     1 /*事件与委托*/
     2 
     3 using System;
     4 delegate void Handler();
     5  
     6 class Incrementer//发布者
     7 {
     8     public event Handler CountedADozen; //定义CountedADozen事件
     9     public void DoCount()//触发事件的方法
    10     {
    11         for (int i = 1; i < 50; i++)
    12          {//每增加12个计数就触发事件一次,私有委托为空就不执行
    13             if (i % 12 == 0 && CountedADozen != null)
    14             {
    15                 CountedADozen();
    16             }
    17         }
    18     }
    19 }
    20   
    21  
    22 class Dozens
    23 {
    24     public Dozens(Incrementer incrementer)//在发布者私有委托里增加方法
    25     {
    26         incrementer.CountedADozen += IncrementDozensCount;
    27     }
    28 
    29     void IncrementDozensCount()//事件成员被触发时要调用的方法
    30     {
    31         Console.WriteLine("Dozens");
    32     }
    33 } 
    34  
    35  
    36 class SomeOtherClass
    37 {
    38     public SomeOtherClass(Incrementer incrementer)
    39     {
    40         incrementer.CountedADozen += DoSomething;//在发布者私有委托里增加方法
    41     }
    42  
    43     public void DoSomething()//事件成员被触发时要调用的方法
    44     {
    45         Console.WriteLine("SomeOtherClass");
    46     }
    47 }
    48  
    49 
    50 class Program
    51 {
    52     static void Main()
    53     {
    54         Incrementer incrementer = new Incrementer();
    55         Dozens dozensCounter = new Dozens(incrementer);
    56         SomeOtherClass other = new SomeOtherClass(incrementer);  
    57         
    58         incrementer.DoCount();
    59         
    60         Console.Write("Press any key to continue . . . ");
    61         Console.ReadLine();
    62     }
    63 }
    发布者与订阅者

    定义及使用事件的6步曲

      公用的

        声明事件参数类: class xxxEventArgs{}

        声明委托: delegate void xxxEventHandler(obj, args)

      在一个类中 

        定义事件: public event 类型 名称

        发生事件: 在这个类的方法中,事件名(参数)

      在别的类中

        定义一个方法: void 方法名(obj, args)

        注册事件 : xxx.事件 += new 委托(方法名)

           (可以使用匿名函数或lamda表达式进行注册)

    1 this.button1.Click += new System.EventHandler(this.button1_Click);
    2 private void button1_Click(object sender, EventArgs e)
    3 {
    4     this.label1.Text = DateTime.Now.ToString();
    5 }
    按钮点击事件
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Text;
     4  
     5 namespace UsingEvent
     6 {   //声明一个委托
     7     public delegate void ClickEventHandler(object sender, EventArgs e);
     8 
     9     public class MyButton     //创建MyBottom
    10     {
    11         public event ClickEventHandler ClickEvent;//声明一个事件
    12  
    13         public void Click()    //单击MyButton
    14         {
    15             if (ClickEvent != null)
    16             {
    17                 Console.WriteLine("MyButton: 我被单击了");
    18                 ClickEvent(this, null);   //抛出事件,给所有响应者
    19             }
    20         }
    21     }
    22  
    23     public class MyForm
    24     {
    25         public MyButton myButton = new MyButton();
    26  
    27         public MyForm()
    28         {
    29             //注册事件,当myButton被单击的时候就会调用响应的处理函数 
    30             myButton.ClickEvent += new ClickEventHandler(OnClickEvent); 
    31             /*myButton.ClickEvent += OnClickEvent;  */ 
    32         }
    33  
    34        //事件处理函数
    35        void OnClickEvent(object sender, EventArgs e)
    36         {
    37             Console.WriteLine("MyForm: 我知道你被单击了!");
    38         }
    39     }
    40  
    41     class Program
    42     {
    43         static void Main(string[] args)
    44         {
    45             MyForm form = new MyForm();//生成一个MyForm
    46             form.myButton.Click();//单击MyForm中的鼠标,效果就出来了
    47             Console.ReadLine();
    48         }
    49     }
    50 }
    使用事件 模拟窗体 按钮

    事件与委托的关系

    事件有点像委托类型的实例

      事件一定有相关的委托类型

      与委托实例一样,事件也“包含”多个函数

      事件的运算受更多限制(在类外只能用+=或-=)

    事件比委托实例更复杂

    可以定义事件存取器

      修饰符 event 委托类型名 事件名   

      { 

        add { e += value; } 

        remove { e -= value; } 

      }

      1 using System;
      2 
      3 /*     声明委托
      4     DownloadStartHandler
      5     DownloadEndHandler
      6     DownloadingHandler */
      7 public delegate void DownloadStartHandler(object sender, DownloadStartEventArgs e);  
      8 public delegate void DownloadEndHandler(object sender, DownloadEndEventArgs e);  
      9 public delegate void DownloadingHandler(object sender, DownloadingEventArgs e);  
     10 
     11 //DownloadStart事件参数类
     12 public class DownloadStartEventArgs
     13 {
     14     public string Url{ get{ return _url;} set{ _url=value;} }
     15     private string _url;
     16 
     17     public DownloadStartEventArgs( string url ){ this._url = url; }
     18 }
     19 
     20 //DownloadEnd事件参数类
     21 public class DownloadEndEventArgs
     22 {
     23     public string Url{ get{ return _url;} set{ _url=value;} }
     24     private string _url;
     25 
     26     public long ByteCount { get { return _byteCount; } set{ _byteCount=value;} }
     27     private long _byteCount;
     28 
     29     public DownloadEndEventArgs( string url, long size  ){ this._url = url; this._byteCount=size; }
     30 }
     31 
     32 //Downloading事件参数类
     33 public class DownloadingEventArgs
     34 {
     35     //网址属性
     36     public string Url{ get{ return _url;} set{ _url=value;} }
     37     //网址字段
     38     private string _url;
     39 
     40     //下载比例属性
     41     public double Percent { get { return _percent; } set{ _percent=value;} }
     42     //网址数据下载比例字段
     43     private double _percent;
     44 
     45     //构造函数
     46     public DownloadingEventArgs( string url, double percent  ){ this._url = url; this._percent=percent; }
     47 }
     48 
     49 
     50 public class Crawler
     51 {
     52     //事件
     53     public event DownloadStartHandler DownloadStart;  
     54     public event DownloadEndHandler DownloadEnd;  
     55     public event DownloadingHandler Downloading;  
     56 
     57     //属性
     58     public string Name { get{return name;} set{ name=value;} }
     59     //字段
     60     private string name;
     61     private string site;
     62 
     63     public Crawler( string name, string site )
     64     {
     65         this.name = name;
     66         this.site = site;
     67     }
     68 
     69     //事件触发方法
     70     public void Craw()
     71     {   
     72         while( true )
     73         {
     74             //获取下一个网址
     75             string url = GetNextUrl();
     76             if( url == null ) break;
     77             
     78             //获取网址数据大小
     79             long size = GetSizeOfUrl( url ); 
     80 
     81             //DownloadStart事件是否注册
     82             if( DownloadStart != null )
     83             {
     84                 DownloadStart( this, new DownloadStartEventArgs(url));
     85             }
     86 
     87             //模拟下载, 间隔100毫秒,下载1024的数据(+1024)
     88             for( long i=0; i<size+1024; i+=1024 )
     89             {
     90                 //间隔100毫秒
     91                 System.Threading.Thread.Sleep( 100 );
     92                 
     93                 //计算下载比例
     94                 double percent = (int)(i*100.0/size);
     95                 if( percent>100)  percent=100;
     96 
     97                 //Downloading事件是否注册
     98                 if( Downloading != null ) 
     99                 {                
    100                     //事件发生,传事件参数(Crawler类对象, DownloadingEventArgs参数类对象 )
    101                     /* DownloadingEventArgs参数类对象参数
    102                     (Crawler类方法GetNextUrl获取的url, 
    103                      Crawler类方法GetSizeOfUrl获取的url的数据大小,计算的下载比例percent)*/
    104                     Downloading( this, new DownloadingEventArgs(url, percent));
    105                 }
    106             }
    107 
    108             //DownloadEnd事件是否注册
    109             if( DownloadEnd != null ) 
    110             {
    111                 //DownloadEnd事件发生,调用ShowEnd
    112                 DownloadEnd( this, new DownloadEndEventArgs(url, size));
    113             }
    114         }
    115     }
    116 
    117     //获取下一个网址
    118     private string GetNextUrl()
    119     {
    120         //模拟获取网址,随机产生网址编号,对字段site进行加工
    121         int a = rnd.Next(10);
    122         if( a == 0 ) return null;
    123         return site + "/Page" + a + ".htm";
    124     }
    125 
    126     //获取网址数据大小
    127     private long GetSizeOfUrl( string url)
    128     {
    129         //模拟网址数据大小, 随机产生网址数据大小
    130         return rnd.Next(3000 * url.Length);
    131     }
    132 
    133     //字段
    134     private Random rnd = new Random();
    135 }
    136  
    137 class Test
    138 {
    139     static void Main()
    140     {
    141         Crawler crawler = new Crawler("Crawer101", "http://www.pku.edu.cn");
    142 
    143         //注册事件
    144         crawler.DownloadStart += new DownloadStartHandler( ShowStart ); 
    145         crawler.DownloadEnd += new DownloadEndHandler( ShowEnd );
    146         crawler.Downloading += new DownloadingHandler( ShowPercent );  
    147 
    148         //触发事件
    149         crawler.Craw();
    150         
    151         Console.ReadKey();
    152     }
    153 
    154     static void ShowStart(object sender, DownloadStartEventArgs e){
    155         Console.WriteLine( (sender as Crawler).Name + "开始下载" + e.Url );
    156     }
    157 
    158     static void ShowEnd(object sender, DownloadEndEventArgs e){
    159         Console.WriteLine( "
    
    下载" + e.Url + "结束,其下载" + e.ByteCount + "字节" );
    160     }
    161 
    162     static void ShowPercent(object sender, DownloadingEventArgs e){
    163         //DownloadingEventArgs参数类对象, e的Url属性
    164         Console.Write( "
    下载" + e.Url + "......." + e.Percent + "%" );        
    165     }
    166 }
    网络爬虫
  • 相关阅读:
    python 面向对象(三大特性)
    python 发红包
    python 计算器
    python 模块和包
    python 异常处理
    python 序列化模块
    python 常用模块
    esriSRGeoCS3Type Constants
    esriSRGeoCS2Type Constants
    esriSRGeoCSType Constants
  • 原文地址:https://www.cnblogs.com/GoldenEllipsis/p/10349878.html
Copyright © 2020-2023  润新知