zoukankan      html  css  js  c++  java
  • C# 委托和事件,简单示例说明问题

    先看看示例效果

    按照国际惯例,得先说说概念。

    委托(C# 编程指南)

    事件(C# 编程指南)

    以上内容来自MSDN。

    委托源码

    【委托】

    概念和代码都有了。剩下的就是应用了,要是只知道概念不会用,那还是等于不会。

    要用委托首先要明确几个问题:

    1、为什么需要委托?什么场合用?

      我也不想使用委托,谁没事想多些代码。但是在某一天,我写代码的时候,在多线程中访问了 UI 控件,发现不行。于是乎百度一大堆,结果就是用委托。官方也有这样的Demo,具体自己百度。于是乎得到一个答案,多线程访问 UI 控件得借助委托。其他的场景不说了,其实大部分都是多线程和异步的场景需要。到这里我们就明白了,委托这东西,可以在多线程或者异步操作中发挥大作用,可以在窗体间传参,而且还很安全。

    2、怎么使用? 

      委托的使用也是比较容易的。

      1)、定义委托

      2)、声明委托对象

      3)、实例化委托

      4)、调用委托(执行方法)

    来点实际的代码,多线程中访问 UI 控件:

    public delegate void UpdateTextEventHandler(string strText); // 1、定义委托类型
    
            public UpdateTextEventHandler UpdateText; // 2、声明委托对象public FrmMain()
            {
                InitializeComponent();
    
                UpdateText = OnUpdateText; // 3、实例化委托对象,这里编译后就不是这样子了,而是有个 new 操作
            }
    
            private void OnUpdateText(string strText)
            {
                labTest.Text = strText;
            }
    
            private void btnThreadOperateControl_Click(object sender, EventArgs e)
            {
                new Task(() =>
                {
                    // 这里就不得不使用委托了,否则会报错,提示大概意思就是“不能再其他线程访问控件"
                    for (int i = 0; i < 1000; i++)
                    {
                        // 自定义委托方式
                        //Invoke(UpdateText, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
    
                        // 采用泛型委托简化后
                        Invoke(new Action<string>(strText => labTest.Text = strText), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
    
                        System.Threading.Thread.Sleep(10);
                    }
                }).Start();
            }

    以上代码比较简单,但可以解决一些基本的多线程访问控件问题。现实场景有:后台多线程操作业务,打印操作日志到主界面Text框。后台采集数据,更新到主界面Chart。

    当然,委托作为C#的一个很核心的东西,远不止这些内容。有多播委托,将委托作为函数参数进行封装等。

    委托类似:c/c++中的函数指针封装版,MFC/C++Builder中的PostMessage/SendMessage封装版,Qt中的信号槽。

    一道华丽的分割线


    【事件】

    使用事件也要弄清楚几个问题

    1、为什么使用委托?什么场合用?

      事件是对多播委托的一个封装,主要是限制谁发布事件,谁触发。比如自己定义一个类,类里面有个事件,那么只能你来触发,响应在别人那边。事件多用于UI操作,但不代表非UI不可以使用。窗体程序将这一点体现的淋漓尽致。

    2、怎么使用?

      事件的使用也是比较容易的。

      1、由于事件是基于委托的,那么你得先定义一个委托类型

      2、声明委托对象,并用event关键字修饰

      3、在声明事件的类内部使用(谁声明的,谁触发)

      4、在声明事件的类的外部绑定(没有声明的,那你就来订阅(绑定 +=)事件)

    来点实际代码:

    using System;
    
    namespace EventDemo
    {
        public delegate void TestEventHandler();
    
        class Program
        {
            static void Main(string[] args)
            {
                Class1 class1 = new Class1();
                class1.Test1 = Test;
                // 委托调用,这里代表是Program类调用class1.Test1(),可不能理解成class1调用
                class1.Test1();
    
                class1.Test += Test;
                // 事件调用,这里对事件的体现不是很明显,因为能看到调用了DoSomething。
                // 虽然调用了DoSomething,但是事件是在Class1内部调用的
                class1.DoSomething();
    
                Console.WriteLine("Press any key to close the application...");
                Console.ReadKey(true);
            }
    
            static void Test()
            {
                Console.WriteLine("hello world.");
            }
        }
    
        class Class1
        {
            public TestEventHandler Test1; // 声明委托对象
    
            public event TestEventHandler Test; // 声明事件对象
    
            public void DoSomething()
            {
                Test?.Invoke();
            }
    
        }
    
    }

    个人经验分享2句话区分委托和事件:

    1、委托一般是自己声明,别人调用。

    2、事件是自己声明,自己调用,但是响应在别人那边。

    看完了这些,不要以为你就会使用委托和事件,只能说明你看了我的文章,谢谢。

    demo

  • 相关阅读:
    JavaEE——SpringMVC(11)--拦截器
    JavaEE——SpringMVC(10)--文件上传 CommonsMultipartResovler
    codeforces 460A Vasya and Socks 解题报告
    hdu 1541 Stars 解题报告
    hdu 1166 敌兵布阵 解题报告
    poj 2771 Guardian of Decency 解题报告
    hdu 1514 Free Candies 解题报告
    poj 3020 Antenna Placement 解题报告
    BestCoder5 1001 Poor Hanamichi(hdu 4956) 解题报告
    poj 1325 Machine Schedule 解题报告
  • 原文地址:https://www.cnblogs.com/hjsstudio/p/9816126.html
Copyright © 2011-2022 走看看