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、事件是自己声明,自己调用,但是响应在别人那边。
看完了这些,不要以为你就会使用委托和事件,只能说明你看了我的文章,谢谢。
上一篇: C++11中weak_ptr的使用
下一篇: c++中数据大小的计算