经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C# » 查看文章
C# 委托和事件,简单示例说明问题
来源:cnblogs  作者:碧水青荷  时间:2018/10/20 15:37:59  对本文有异议

先看看示例效果

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

委托(C# 编程指南)

事件(C# 编程指南)

以上内容来自MSDN。

委托源码

【委托】

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

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

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

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

2、怎么使用? 

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

  1)、定义委托

  2)、声明委托对象

  3)、实例化委托

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

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

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

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

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

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

 

一道华丽的分割线


 

【事件】

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

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

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

2、怎么使用?

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

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

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

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

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

 

来点实际代码:

  1. using System;
  2. namespace EventDemo
  3. {
  4. public delegate void TestEventHandler();
  5. class Program
  6. {
  7. static void Main(string[] args)
  8. {
  9. Class1 class1 = new Class1();
  10. class1.Test1 = Test;
  11. // 委托调用,这里代表是Program类调用class1.Test1(),可不能理解成class1调用
  12. class1.Test1();
  13. class1.Test += Test;
  14. // 事件调用,这里对事件的体现不是很明显,因为能看到调用了DoSomething。
  15. // 虽然调用了DoSomething,但是事件是在Class1内部调用的
  16. class1.DoSomething();
  17. Console.WriteLine("Press any key to close the application...");
  18. Console.ReadKey(true);
  19. }
  20. static void Test()
  21. {
  22. Console.WriteLine("hello world.");
  23. }
  24. }
  25. class Class1
  26. {
  27. public TestEventHandler Test1; // 声明委托对象
  28.  
  29. public event TestEventHandler Test; // 声明事件对象
  30.  
  31. public void DoSomething()
  32. {
  33. Test?.Invoke();
  34. }
  35. }
  36. }

 

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

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

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

 

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

demo

 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号