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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM