正确调用事件处理程序

简介: 正确调用事件处理程序

不管是刚接触 C# 还是已经具有多年开发经验的大部分人会觉得事件处理很简单,只需要把事件定义好然后在需要的时候出发它就可以了。其实这种想法是错误的,这里面有很多需要注意的问题。下面这段代码是大部分开发人员经常使用的定义事件处理程序的方法。

public class EventDemo
{
    private EventHandler<int> demo;
    public void DemoEvent()
    {
        demo(this);
    }
}

上面的代码中存在一个严重的问题,当在对象上触发 demo 事件时并没有关联的事件处理程序的话,C# 将会用 null 值来表示没有处理程序与该事件相关联,进而将会引发 NullReferenceException 异常。针对这个问题大部分程序员会做如下修改:

public void DemoEvent()
{
    if(demo!=null)
    {
        demo(this);
    }
}

这种修改方法解决了上述大部分问题,但是还存在一个隐藏的问题。当有多个线程都调用这个事件是就会出现线程之间相互争夺,举个例子来说就是线程 A 在执行到 if (demo!=null)时发现 demo 不等于 null ,正巧这时线程 B 将唯一的事件处理程序解除了订阅,这时线程 A 再调用 demo 时事件处理程序已经变为了 null ,进而导致 NullReferenceException 异常。真多这个问题一些程序员又会做如下的修改:

public void DemoEvent()
{
    var handler = demo;
    if(handler!=null)
    {
        handler(this);
    }
}

上述这种方法是对等号右侧的内容进行了浅拷贝创建了新的引用,使其指向原来的事件处理程序(相当于给事件订阅者生成了一个快照),当另一个进程注销掉事件处理程序时,注销的只是 demo 上所绑定的处理程序,因此当当前的线程执行 handler 时是不会出现 NullReferenceException 异常。这种解决方法是网上所能搜的方法之一,也是绝大部分开发人员所推荐的解决方法。但是这个方法会使代码显得难以理解(尤其是对于开发新手),并且代码稍显冗余。于是在 C# 6.0 中微软为我们增加了 null 条件运算符(?.)。null 条件运算符可以安全的调用事件处理程序并且使代码清晰明了还简单。首先它会判断运算符左侧的内容是否为 null ,如果是 null 就跳过该语句,反之执行运算符右侧的内容。下面我们利用 null 条件运算符对前面的代码进行一下改进。

public void DemoEvent()
{
    demo?.Invoke(this);
}

Tip:使用 null 条件运算符有一点需要注意,运算符右侧不允许直接出现括号,因此必须使用 Invoke 进行触发事件。每定义一个委托或者时间编译器就会生成一个 Invoke 方法。


进行触发事件。每定义一个委托或者时间编译器就会生成一个 Invoke 方法。

目录
相关文章
|
算法 物联网 开发者
【手把手教程】无限场景风格LoRA与固定人物LoRA的融合-酷蛙FaceChain0826周记(GitHub已4K Star!)
酷蛙FaceChain项目计划后续联合社区的力量不断打磨该开源项目,解锁更多高阶玩法(比如人物表情包、人物连环画故事、虚拟试衣间……),并进行更深层次的算法创新,发表相应顶会论文。
|
Web App开发 JavaScript Java
XWalkView+html 开发Android应用
在Android开发中有时候为了开发简洁和方便移植,采用了Html+WebView的开发模式,然而Android自带的WebView控件是调用的本机的浏览器内核,有些版本较老的手机浏览器和手机性能都不能满足需求(表现在html5不兼容、体验不流畅等地方)。
2411 0
|
11月前
|
负载均衡 算法 应用服务中间件
nginx反向代理与负载均衡
nginx反向代理与负载均衡
324 2
|
6月前
|
小程序 Java 关系型数据库
weixin025移动学习平台的设计与实现+ssm(文档+源码)_kaic
基于微信小程序的移动学习平台旨在解决传统APP占用过多手机存储空间的问题,提升用户体验。该平台使用微信开发者工具开发前端,SSM框架和Java语言开发后台,并采用MySQL数据库保存数据。系统支持管理员对教师、课程、学生信息进行管理,教师可查看及审核作业,管理课程资源;学生能提交作业、查看审核结果并收藏或评论课程资源。此平台使用户无需安装独立APP即可访问学习内容,极大提升了便捷性和管理效率。 关键词:基于微信小程序的移动学习平台;微信开发者工具;SSM框架
|
10月前
|
机器学习/深度学习 存储 人工智能
【大语言模型】ACL2024论文-01 Quantized Side Tuning: Fast and Memory-Efficient Tuning of Quantized Large Language
本文介绍了Quantized Side Tuning(QST)方法,旨在解决大型语言模型(LLMs)微调过程中的内存效率和速度问题。QST通过将模型权重量化为4位,并引入一个与LLM分离的侧网络,显著减少了内存占用并加快了微调速度,同时保持了与现有技术相当的性能。实验表明,QST可以将总内存占用减少高达2.3倍,并将微调速度提高高达3倍。
238 0
|
11月前
|
Ubuntu Docker 容器
本地wsl的Ubuntu安装docker,不使用docker桌面版
本文提供了在WSL的Ubuntu环境中安装Docker引擎的步骤,包括安装引擎、配置iptables以及启动Docker服务。
916 2
|
存储 关系型数据库 PostgreSQL
PostgreSQL有何特点?
【8月更文挑战第5天】PostgreSQL有何特点?
520 6
|
Prometheus Kubernetes 网络协议
k8s学习笔记之CoreDNS
k8s学习笔记之CoreDNS
|
存储 安全 小程序
什么是云计算,为什么选择阿里云?
阿里云提供的云计算服务让您能以按需、按量的方式获取算力,涵盖计算、存储、网络等多种形态,无需自建数据中心。它具备弹性、敏捷、安全、稳定、高性能和低成本等优势,支持业务快速创新,保障数据安全及业务连续性,帮助您专注于核心业务发展。常见应用场景包括网站、小程序、移动应用及大模型问答机器人等。
404 1
都8102年了,还用fastq-dump,快换fasterq-dump吧
之前写过一篇文章Fastq-dump: 一个神奇的软件, 详细介绍了fastq-dump的用法。 虽然fastq-dump参数很多,而且一直被吐槽参数说明写的太差,但是如果真的要用起来其实也就是一行代码 fastq-dump --gzip --split-3 --defline-qual &#39;+&#39; --defline-seq &#39;@$ac-$si/$ri&#39; SRRXXXXX| SRRXXXX.sra # 加上--gzip后需要时间进行文件压缩 当然除了参数问题,还有一个让人诟病的地方就是他只能单个线程,所以速度特别的慢。
5255 0
都8102年了,还用fastq-dump,快换fasterq-dump吧