C#中委托及事件的使用

一、简介

简单记录一下在c#中,委托以及事件的使用方法

二、委托

2.1 委托是什么?

委托是一个类,可以将方法当作参数进行传递,保存对函数的引用。可以将委托看成执行方法的一个东西。

2.2 委托如何声名?

需要使用关键字delegate声名

public delegate void MyNoReturnNoParaDelegate ();//无参数无返回值委托
public delegate void MyNoReturnWithParaDelegate (int x, int y);//带参无返回值委托
public delegate int MyWithReturnWithParaDelegate (int x, int y);//带参有返回值委托

2.3 委托如何使用?

private void NoReturnNoParaMethod()
{
    Console.WriteLine("This is NoReturnNoParaMethod");
}

private void NoReturnWithParaMethod(int x, int y)
{
    Console.WriteLine($"This is NoReturnWithParaMethod Para1:{x},Para2:{y}");
}

private int WithReturnWithParaMethod(int x, int y)
{
    Console.WriteLine($"This is WithReturnWithParaMethod Para1:{x},Para2:{y}");
    return x + y;
}

private void InitDelegate()
{
    MyNoReturnNoParaDelegate myNoReturnNoParaDelegate = new MyNoReturnNoParaDelegate(NoReturnNoParaMethod);
    MyNoReturnWithParaDelegate myNoReturnWithParaDelegate = new MyNoReturnWithParaDelegate(NoReturnWithParaMethod);
    MyWithReturnWithParaDelegate myWithReturnWithParaDelegate = WithReturnWithParaMethod;//可以省去new
  //使用Invoke委托中所引用的方法
    myNoReturnNoParaDelegate.Invoke();
    myNoReturnWithParaDelegate.Invoke(1, 2);
    int sum = myWithReturnWithParaDelegate(1, 2);//也可以省去Invoke
}

2.4 多播委托

一个委托实例可以加入多个方法,当使用Invoke调用的时候,就会按照添加的顺序执行对应的方法

MyNoReturnNoParaDelegate myNoReturnNoParaDelegate = new MyNoReturnNoParaDelegate(NoReturnNoParaMethod);//实例化委托,并传入第一个方法
myNoReturnNoParaDelegate += NoReturnNoParaSecondMethod;//添加第二个方法
myNoReturnNoParaDelegate.Invoke();//执行
myNoReturnNoParaDelegate -= NoReturnNoParaSecondMethod;//从委托实例中注销第二个方法

2.5 官方提供的两种委托Action与Func

Action:没有返回值,参数可有可无,最多支持16个泛型参数,使用方法与自定义委托类类似

Action action= new Action(NoReturnNoParaMethod);
action.Invoke();

Func: 必须有返回值,参数可有可无,最多支持16个泛型参数,使用方法与自定义委托类类似

Func<int, int,int> func1 = new Func<int, int,int>(WithReturnWithParaMethod);
int sum = myWithReturnWithParaDelegate(1, 2);

2.6 委托使用场景

当一个方法大部分代码相同,只有判断逻辑不同时,可以将判断逻辑通过委托来执行

public static IEnumerable<T> ElevenWhere<T>(IEnumerable<T> source, Func<T, bool> func)
{
    List<T> TList = new List<T>();
    foreach (T item in source)
    {
        if (func.Invoke(item))
        {
             studentList.Add(item);
        }
    }
    return TList ;
}    

三、事件

3.1 事件是什么?

事件是委托的子集,可以使用事件的地方都可以使用委托来代替,事件对于操作者有一定的权限限制,订阅者只能订阅和取消订阅,更加安全。事件就是为广播/订阅这种模式而生。

3.2 事件使用方式

首先需要一个广播者和至少一个订阅者,广播者通过委托字段定义一个事件,通过事件进行广播,而订阅者也必须有与对应的功能,来订阅这个事件。

先使用c#中的 EventHandler 和 EventArgs

3.2.1 首先需要一个传递消息的类

public class PublishEventArgs : EventArgs
{
    public string Msg { get; set; } //传递数据。
}

 

3.2.2 然后需要一个事件发布者

public class EventPublishEvent
{
    //1、创建事件并发布
    public event EventHandler<PublishEventArgs> OnPublish;

    public void Publish()
    {
            PublishEventArgs argContent = new PublishEventArgs();
            argContent.Msg = "消息传递";
            //2、触发事件  
            OnPublish?.Invoke(this, argContent);
  }
}

3.2.3 最后需要一个订阅者

public class Subscriber
{
    public Subscriber(EventPublishEvent npo)
    {
        npo.OnPublish += SubscriptinMsg;  //3、订阅事件
    }

    void SubscriptinMsg(object sender, PublishEventArgs e)
    {
        Console.WriteLine("接收到消息:"+ e.Msg);
    }
}

当  npo.Publish() 执行的时候,方法SubscriptinMsg()就会被执行,并且可以接收到传过来的数据。

注:为事件定义委托,必须是void类型,建议委托名字EventHandler结尾

四、委托的异步执行

4.1 BeginInvoke()

当我们执行委托时,不想阻塞当前线程,我们就需要使用到异步执行委托,也就是使用BeginInvoke()方法

Action<string> act = (s) =>
{
    Console.WriteLine("开始执行方法...");
    Thread.Sleep(1000);             
    Console.WriteLine($"执行结束 :{s}");
};
act.BeginInvoke("测试",null,null);

4.2 AsyncCallback()与 EndInvoke()

当我们想要在执行完委托后再执行一些其他的操作,就可以使用到回调AsyncCallback

IAsyncResult asyncResult = null;
AsyncCallback callback = ar =>
{
    Thread.Sleep(3000);
    Console.WriteLine($"传入回调参数 {ar.AsyncState}");
};
Action<string> act = (s) =>
{
    Console.WriteLine("开始执行方法。。。");
    Thread.Sleep(1000);

    Console.WriteLine($"执行结束 :{s}");
};
act.BeginInvoke("测试", asyncResult, 1);
act.EndInvoke(asyncResult);//使用EndInvoke等待会阻塞当前线程,直到委托执行完毕
使用EndInvoke等待会阻塞当前线程,直到委托执行完毕,不会等待回调也执行结束

  

 

 

posted @ 2022-09-01 19:48  just--like  阅读(2330)  评论(0编辑  收藏  举报