zoukankan      html  css  js  c++  java
  • c# 委托探究

    什么时候使用委托呢?

    1.程序中有的方法很耗时,而调用这个耗时方法返回的结果值,需要在接下来的代码中使用到,这时使用委托,将耗时方法与委托绑定(Func),在使用委托的异步调用BeginInvoke,程序代码接着处理其它项,需要时使用 Func.EndInvoke(AsyncResult)得到耗时方法的结果值

    (除了这种需要使用返回值的情况,假设耗时方法去完成界面的一部分工作,而另一部分工作由其它代码块完成,使用委托的异步调用,二者并行执行,缩短程序执行时间)

    2.async/await 与Task.Run() 结合使用,异步调用,并且界面上不会卡死(经测试第1种调用耗时方法时界面无法响应用户其它的操作),Task是线程池的升级版,使用Task.Run不一定会创建新线程,也可能在空闲的线程执行,查看Task.Run,如下图,也是结合委托来使用的

    3.父子界面,父子控件 可以使用委托和事件, 还有常见的观察者模式(一对多),比如猫叫了,老鼠跑了 主人醒了

     上面两种具体的使用参考:

    一.委托类别

    1)delegate

    delegate至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型

    例:public delegate int MethodtDelegate(int x, int y);表示有两个参数,并返回int型

    上述委托绑定的方法也必须是返回类型为int,参数为int,且为2个

    2)Action Action是无返回值的泛型委托。

    Action 表示无参,无返回值的委托

    Action<int> 表示有传入参数int;无返回值的委托

    Action<int,string> 表示有传入参数int,string ;无返回值的委托

    ......

    3)Func

    Func是有返回值的泛型委托

    Func<int> 表示无参,返回值为int的委托

    Func<int,string>表示传入参数为int类型,返回值为string类型

    .......

     Func至少0个参数,至多16个参数,根据返回值泛型返回。必须有返回值,不可void


    二、委托调用

    1.同步调用

    Invoke

    2.异步调用

    BeginInvoke,

    BeginInvoke 方法参数不定,但是最后两个参数固定,其中倒数第2个参数,到时第1个参数为必须,若没有,传入null,
    倒数第2个参数表示回调函数,倒数第1个参数表示传给回调函数的参数内容

    三、调用例子代码

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public partial class frmWeiTuo : Form
        {
            public frmWeiTuo()
            {
                InitializeComponent();
            }
    
            public delegate string testEventHander(string arg);
          
    
    
            private void btnAction_Click(object sender, EventArgs e)
            {
                this.richTextBox1.Text = "";
                //Action委托,Func 委托 作为方法的类型,
                //Test(msg, "huanggang");
                //Test(msg, 30);
               
                TestFunc(msgFunc,"shifang");
                TestFunc(msgFunc,31);
    
    
                //delegate 委托
                //将方法msgDelegate 与委托绑定,
                //testEventHander testEvent = new testEventHander(msgDelegate);
                //MessageBox.Show( msgDelegate("huanggang"));
    
            }
            /// <summary>
            ///   Action是无返回值的泛型委托 例如Action<int,string> 表示有传入参数int,string无返回值的委托
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="action"></param>
            /// <param name="p"></param>
            public void Test<T>(Action<T> action, T p)
            {
                //action(p);
    
               // action.Invoke(p); //同步调用
                action.BeginInvoke(p,null,null); //异步调用
                this.richTextBox1.Text += "Test" + "
    ";
    
            }
            /// <summary>
            ///  Func是有返回值的泛型委托
            /// T1为传入参数,T2为函数返回类型 比如Func(string,int) 表示传入参数是string类型,函数返回类型为int
            /// BeginInvoke  方法参数不定,但是最后两个参数固定,其中倒数第2个参数,到时第1个参数为必须,若没有,传入null,
            /// 倒数第2个参数表示回调函数,倒数第1个参数表示传给回调函数的参数内容
            /// </summary>
            /// <typeparam name="T1"></typeparam>
            /// <typeparam name="T2"></typeparam>
            /// <param name="func"></param>
            /// <param name="arg"></param>
            public void TestFunc<T1,T2>(Func<T1,T2> func,T1 arg)
            {
    
              //  this.richTextBox1.Text += func(arg);
    
              //  this.richTextBox1.Text += func.Invoke(arg);//同步
            
                IAsyncResult asyncResult = func.BeginInvoke(arg, null, null);//异步调用,
                
               var result= func.EndInvoke(asyncResult); //接收委托返回的值
                this.richTextBox1.Text += result;
            }
    
            public void msg(string name)
            {
                // 当使用   action.BeginInvoke(p,null,null) 调用时,会报错,提示从不是当前的线程访问
         
                 // this.richTextBox1.Text += name+"
    ";
    
                //action.BeginInvoke(p,null,null) 调用 ,使用线程匿名委托 delegate (){} 匿名委托写法
    
                richTextBox1.BeginInvoke(new ThreadStart(delegate ()
                                {
                                    richTextBox1.Text += name + "
    ";
                                }));
                
            }
            public void msg(int age)
            {
                richTextBox1.BeginInvoke(new ThreadStart(delegate()
                {
                    richTextBox1.Text += age + "
    ";
                }));
              
            }
            public string msgFunc(string name)
            {
                //this.richTextBox1.Text += name + "
    ";
                return name + "
    ";
            }
            public int msgFunc(int age)
            {
                return age;
            }
    
            public string msgDelegate(string name)
            {
                //this.richTextBox1.Text += name + "
    ";
                return name + "
    ";
            }
            public int msgDelegate(int age)
            {
                return age;
            }
    
            private void btnAsync_Click(object sender, EventArgs e)
            {
                Action<string> ac = msg;
                ac("huanggang");
    
                //匿名函数的写法,Lambda写法 ,可以理解为委托类型的对象
                Action<string> ac1 = (t) => { msg(t); };
    
                Action<int> ac2 = (a) => { msg(a); };
                ac1.Invoke("石芳");
                ac2.Invoke(30);
                testEventHander testEvent = msgDelegate;
                testEvent("30");
            }
        }
    }

     以上,若不有不对的,大家多批评指正,谢谢!

    本文参考链接:

    https://www.cnblogs.com/yaopengfei/p/8094512.html

    https://www.cnblogs.com/mq0036/p/9166893.html

  • 相关阅读:
    Gym 100801D Distribution in Metagonia (数学思维题)
    Gym 100801E Easy Arithmetic (思维题)
    GNOME编辑器--gedit 构建基本脚本
    linux默认编辑器 sublime
    su和su-命令的本质区别
    #ifdef #ifndef使用
    linux 安装软件程序
    linux命令行与shell脚本编程大全---更多bash shell命令
    预处理语句--#define、#error和#warning
    FW开发代码规范---小任性(2)
  • 原文地址:https://www.cnblogs.com/gudaozi/p/12189561.html
Copyright © 2011-2022 走看看