title author date CreateTime categories
C#委托
lindexi
2019-09-02 12:57:37 +0800
2018-2-13 17:23:3 +0800
C#

关于什么是委托,委托如何使用,我在这里就不说了。
需要说的:

  1. 委托是函数指针链
  2. 委托的 BeginInvoke
  3. 委托如果出现异常,会如何

如果不知道函数指针,可以继续往下看,我来告诉大家,为何需要委托。

假如在写游戏,有一个人物,他会升级,那么在他升级的时候,需要给他添加潜力值,而判断升级是经验类需要写的。

先写一个经验类。

    核心
如果当前经验大于最大经验,升级。

但是升级是在经验类里,经验类外的人物不会知道已经升级了,那么如何让人物知道升级?

这时可以使用委托。

     如果当前经验大于最大经验
调用函数升级

那么函数 升级 如何让人物知道,可以使用一个委托

    升级
调用委托

于是人物可以添加函数到经验。

    经验.升级=人物.升级

这样,经验的升级就是使用人物的升级,可以使用其他类的函数。

上面没有代码,现在来说个有代码的。

假如需要去寄快递,那么需要找邮递,把东西给他

假设有个邮递,可以寄快递

    class 邮递
{ public static Action 寄快递;
}

委托最好用Action

这里定义委托是,不知道会是哪个快递员会去寄快递,在实际,谁也不知道最后是哪个,快递员可能说不想干了,实际快递太辛苦,大家多体谅。所以不能写函数说,快递A 给 小明去寄,因为不知道小明是不是今天上班。

来写一个 主角 张 ,他需要去寄快递。

    class MrZhang
{
public void 寄快递()
{
邮递.寄快递();
} }

不知道是谁上班,但是我可以寄快递。

最后,今天来上班的快递员

    快递员 a = new 快递员();
邮递.寄快递 = a.寄快递; class 快递员
{ public void 寄快递()
{ }
}

就是快递,所以这就是委托使用。

使用一个函数,不知道他是谁用的,可以使用委托。

如果使用的委托是 多播,那么小心用 BeginInvoke

如果使用 同步,那么多个方法是可以运行

            static void Main(string[] args)
{
Action m = M1;
m += M2;
m.Invoke();
} private static void M1()
{
p();
} private static void M2()
{
p();
} private static void p()
{
Console.WriteLine("线程ID为:{0}", Thread.CurrentThread.ManagedThreadId);
}

如果使用的BeginInvoke,那么在委托多播使用 BeginInvoke 会报异常 System.ArgumentException:“The delegate must have only one target.”

在一个线程不能同时执行多个方法,使用 BeginInvoke 必须在多个线程,所以可以使用 获得所有方法,然后执行

        static void Main(string[] args)
{
Action m = M1;
m += M2;
//m.Invoke();
List<IAsyncResult> list=new List<IAsyncResult>();
var invtl = m.GetInvocationList().OfType<Action>().ToList();
foreach (Action temp in invtl)
{
list.Add(temp.BeginInvoke((e) => { }, null));
} for (int i = 0; i < invtl.Count(); i++)
{
invtl[i].EndInvoke(list[i]);
} } private static void M1()
{
p();
} private static void M2()
{
p();
} private static void p()
{
Console.WriteLine("线程ID为:{0}", Thread.CurrentThread.ManagedThreadId);
}

有两个需要知道:

m.GetInvocationList() 得到 Delegate 不能直接执行。

需要转类型,定义是知道他是什么类型,上面使用的是 Action ,所以可以转 Action ,如果是自定义的,那么使用自定义的。

第二,如果使用 BeginInvoke ,在等待时,需要拿到 IAsyncResult 才可以。

    var temp = m.BeginInvoke((e) => { }, null);
m.EndInvoke(temp);

上面代码:如果要使用 BeginInvoke ,小心 Delegate 是多个函数,不是一个函数,所以使用时,建议使用

            var invtl = m.GetInvocationList().OfType<Action>().ToList();
foreach (Action temp in invtl)
{
list.Add(temp.BeginInvoke((e) => { }, null));
}

需要把类型换自己的类型。

如果委托发生异常

如果委托方法里没有 try catch,那么如果使用 invoke, 委托是函数指针链,所以会在执行异常退出。

如果使用 BeginInvoke ,那么会在 EndInvoke 退出。

        static void Main(string[] args)
{
Action m = M1;
m += M2;
//m.Invoke();
List<IAsyncResult> list=new List<IAsyncResult>();
var invtl = m.GetInvocationList().OfType<Action>().ToList();
foreach (Action temp in invtl)
{
list.Add(temp.BeginInvoke((e) => { }, null));
} //for (int i = 0; i < invtl.Count(); i++)
//{
// invtl[i].EndInvoke(list[i]);
//} } private static void M1()
{
p();
throw new ArgumentException();
} private static void M2()
{
p();
throw new ArgumentException();
} private static void p()
{
Console.WriteLine("线程ID为:{0}", Thread.CurrentThread.ManagedThreadId);
}

上面代码没有 EndInvoke 不会有异常,异常发生在别线程,所以不会在Main函数异常。

如果使用 EndInvoke 会在 Main 异常

           static void Main(string[] args)
{
Action m = M1;
m += M2;
//m.Invoke();
List<IAsyncResult> list=new List<IAsyncResult>();
var invtl = m.GetInvocationList().OfType<Action>().ToList();
foreach (Action temp in invtl)
{
list.Add(temp.BeginInvoke((e) => { }, null));
} for (int i = 0; i < invtl.Count(); i++)
{
invtl[i].EndInvoke(list[i]);
} } private static void M1()
{
p();
throw new ArgumentException();
} private static void M2()
{
p();
throw new ArgumentException();
} private static void p()
{
Console.WriteLine("线程ID为:{0}", Thread.CurrentThread.ManagedThreadId);
}

事件

如果事件使用 BeginInvoke 和 委托一样

            _event += (s, e) => M1();
_event += (s, e) => M2();
_event?.BeginInvoke(null, null, (e) => { }, null); private static EventHandler _event;

异常:System.ArgumentException:“The delegate must have only one target.”

需要和 委托 一样,获得函数指针,执行,如果方法里有异常,那么不会在 Main 方法异常,如果没有使用 End 。

            foreach (var temp in _event.GetInvocationList().OfType<EventHandler>())
{
temp.BeginInvoke(null, null, (e) => { }, null);
}

本文还没写好,如果有问题,请联系我

本文内容属于大量抄袭,代码是自己写,但是抄了代码大神写的,于是羞愧放下他的博客:

http://www.cnblogs.com/free722/archive/2011/04/04/2005275.html

http://stackoverflow.com/questions/25979264/understanding-the-wpf-dispatcher-begininvoke

2019-9-2-C#委托的更多相关文章

  1. NET MVC全局异常处理(一) 【转载】网站遭遇DDoS攻击怎么办 使用 HttpRequester 更方便的发起 HTTP 请求 C#文件流。 Url的Base64编码以及解码 C#计算字符串长度,汉字算两个字符 2019周笔记(2.18-2.23) Mysql语句中当前时间不能直接使用C#中的Date.Now传输 Mysql中Count函数的正确使用

    NET MVC全局异常处理(一)   目录 .NET MVC全局异常处理 IIS配置 静态错误页配置 .NET错误页配置 程序设置 全局异常配置 .NET MVC全局异常处理 一直知道有.NET有相关 ...

  2. javascript事件委托和jquery事件委托

    元旦过后,新年第一篇. 初衷:很多的面试都会涉及到事件委托,前前后后也看过好多博文,写的都很不错,写的各有千秋,自己思前想后,为了以后自己的查看,也同时为现在找工作的前端小伙伴提供一个看似更全方位的解 ...

  3. F#周报2019年第26期

    新闻 逐渐演化的.NET Core框架 Visual Studio提示与技巧 Windows Termina(预览) Microsoft在GitHub上的工程师从2000名增加至25000名 视频及幻 ...

  4. 2019阿里云开年Hi购季域名与商标分会场全攻略!

    2019阿里云云上Hi购季活动已经于2月25日正式开启,从已开放的活动页面来看,活动分为三个阶段: 2月25日-3月04日的活动报名阶段.3月04日-3月16日的新购满返+5折抢购阶段.3月16日-3 ...

  5. Masterboxan INC 下半年将聚焦超高净值和家族全权委托客户

    "投资是一个没有终点的奋斗.我们不能简单的预测市场,而是应对市场做出正确的反应.这需要我们不断反思.总结.提升,找到自己的投资哲学,然后用一生的时间去坚守."Masterboxan ...

  6. HTML 事件(三) 事件流与事件委托

    本篇主要介绍HTML DOM中的事件流和事件委托. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流与事件委托 4 ...

  7. C#基础篇 - 理解委托和事件

    1.委托 委托类似于C++中的函数指针(一个指向内存位置的指针).委托是C#中类型安全的,可以订阅一个或多个具有相同签名方法的函数指针.简单理解,委托是一种可以把函数当做参数传递的类型.很多情况下,某 ...

  8. [.NET] C# 知识回顾 - 委托 delegate (续)

    C# 知识回顾 - 委托 delegate (续) [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6046171.html 序 上篇<C# 知识回 ...

  9. [C#] C# 知识回顾 - 委托 delegate

    C# 知识回顾 - 委托 delegate [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6031892.html 目录 What's 委托 委托的属性 ...

  10. 9、委托、事件、Lambda

    开始 关于委托,肯定是要有问题的. 第一个问题,委托用来干什么? 看.net中的表述:在.net平台下,委托类型用来定义和相应应用程序中的回调.(回调?处理内存中两个实体双向通信的一种技术.)   第 ...

随机推荐

  1. 【问题解决方案】单个文件夹嵌套时github仓库中最外层文件夹直接显示所有嵌套文件夹名的问题

    上传文件的时候遇到这样一个问题: 这么看着好像有什么问题,直觉不应该这么显示吧 折腾半天,从github新建了嵌套文件夹并同步到本地,然后从本地push了文件,结果依然显示是这样 好吧,那这个问题应该 ...

  2. kubernetes容器集群管理部署master节点组件

    集群部署获取k8s二进制包 [root@master ~]# wget https://dl.k8s.io/v1.15.0/kubernetes-server-linux-amd64.tar.gz [ ...

  3. 移动终端的GPU显卡介绍

    嵌入式领域里面,不同的SOC芯片往往喜欢采用不同的GPU,目前为止有4家公司提供移动端的GPU芯片:ARM.Imagination Technologies.Vivante和Nvidia (高通Adr ...

  4. org.apache.http.client.HttpClient使用方法

    一.org.apache.commons.httpclient和org.apache.http.client区别(转)   官网说明: http://hc.apache.org/httpclient- ...

  5. 【leetcode】979. Distribute Coins in Binary Tree

    题目如下: Given the root of a binary tree with N nodes, each node in the tree has node.val coins, and th ...

  6. restful规范面试总结

    1.url链接设计:采用https方式,有api关键字,有版本需要明确版本,请求链接用名词来表示资源,具体的操作方式采用请求方式来确定2.url响应数据设计:需要明确 状态码.错误信息.成功结果,子资 ...

  7. Shell脚本并发及并发数的控制

    https://www.jianshu.com/p/701952ffb755 正常情况下,Shell脚本是串行执行的,一条命令执行完才会执行接下来的命令.如下代码: # !/bin/bash for ...

  8. 【dart学习】之字典(Map)的相关方法总结

    一,概述 通常来讲,Map是一个键值对相关的对象,键和值可以是任何类型的对象.每个键只出现一次,而一个值则可以出现多次.映射是动态集合. 换句话说,Maps可以在运行时增长和缩小. dart:core ...

  9. 存储-docker volume 生命周期管理(14)

    volume 生命周期管理 - 每天5分钟玩转 Docker 容器技术(44) Data Volume 中存放的是重要的应用数据,如何管理 volume 对应用至关重要.前面我们主要关注的是 volu ...

  10. [CSP-S模拟测试]:简单的区间(分治)

    题目描述 给定一个长度为$n$的序列$a$以及常数$k$,序列从$1$开始编号.记$$f(l,t)=\sum \limits_{i=l}^ra_i-\max \limits_{i=l}^r\{a_i\ ...