VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > c#编程 >
  • 事件驱动编程——C#开发实时消息通知系统

第一部分:C#基础入门
事件驱动编程——实时消息通知系统
实例介绍
事件驱动编程是响应式系统的核心范式,它通过“发布-订阅”模式实现组件间的解耦:当某个事件发生时(如用户登录、消息发送),系统自动通知所有订阅该事件的组件,无需主动轮询。本节通过实时消息通知系统的场景,展示事件驱动如何实vb.net教程C#教程python教程SQL教程access 2010教程现消息的实时推送(如邮件、短信、APP推送),让你掌握事件驱动的核心思想与实践技巧。
需求分析
设计一个模拟社交APP的实时消息通知系统,核心需求如下:
1.核心事件:
1.用户登录事件(UserLoggedIn):用户登录时触发;
2.消息发送事件(MessageSent):用户发送消息时触发;
2.通知渠道:
1.邮件通知:发送登录提醒或消息通知邮件;
2.短信通知:发送验证码或消息提醒短信;
3.APP推送:发送实时消息推送(如红点提示);
3.事件特性:
1.支持多订阅者(同一事件可绑定多个通知渠道);
2.支持事件取消订阅;
3.事件参数传递(如消息内容、发送者/接收者信息);
4.异常处理:单个通知渠道故障不影响其他渠道。
代码实现

  1. 核心模型与事件参数
    csharp
	using System;
	
	// 用户模型
	public class User
	{
	public int Id { get; set; }
	public string Name { get; set; }
	public string Email { get; set; }
	public string Phone { get; set; }
	public string DeviceToken { get; set; } // APP推送设备令牌
	}
	
	// 消息模型
	public class Message
	{
	public int Id { get; set; }
	public User Sender { get; set; }
	public User Receiver { get; set; }
	public string Content { get; set; }
	public DateTime SentTime { get; set; }
	}
	
	// 自定义事件参数:消息发送事件(继承EventArgs,符合.NET事件设计规范)
	public class MessageSentEventArgs : EventArgs
	{
	public Message Message { get; }
	public bool IsUrgent { get; } // 是否紧急消息
	
	public MessageSentEventArgs(Message message, bool isUrgent = false)
	{
	Message = message;
	IsUrgent = isUrgent;
	}
	}
	
	// 自定义事件参数:用户登录事件
	public class UserLoggedInEventArgs : EventArgs
	{
	public User User { get; }
	public DateTime LoginTime { get; }
	
	public UserLoggedInEventArgs(User user)
	{
	User = user;
	LoginTime = DateTime.Now;
	}
	}
  1. 消息服务类(事件发布者)
    csharp
	// 消息服务:负责事件的发布(触发)
	public class MessageService
	{
	// 事件定义:用户登录事件(使用EventHandler<T>泛型委托,T为事件参数)
	public event EventHandler<UserLoggedInEventArgs> OnUserLoggedIn;
	
	// 事件定义:消息发送事件
	public event EventHandler<MessageSentEventArgs> OnMessageSent;
	
	// 用户登录方法:触发登录事件
	public void UserLogin(User user)
	{
	Console.WriteLine($"
=== 用户{user.Name}登录成功 ===");
	// 触发事件:检查是否有订阅者,避免空引用
	OnUserLoggedIn?.Invoke(this, new UserLoggedInEventArgs(user));
	}
	
	// 发送消息方法:触发消息发送事件
	public void SendMessage(Message message, bool isUrgent = false)
	{
	Console.WriteLine($"
=== 消息发送:{message.Sender.Name} → {message.Receiver.Name} ===");
	// 触发事件:传递自定义参数
	OnMessageSent?.Invoke(this, new MessageSentEventArgs(message, isUrgent));
	}
	}
  1. 通知处理器(事件订阅者)
    csharp
	// 通知处理器:负责事件的订阅与处理
	public class NotificationHandler
	{
	// 邮件通知处理方法
	public void HandleEmailNotification(object sender, EventArgs e)
	{
	switch (e)
	{
	case UserLoggedInEventArgs loginArgs:
	Console.WriteLine($"[邮件通知] 欢迎{loginArgs.User.Name}登录!登录时间:{loginArgs.LoginTime:yyyy-MM-dd HH:mm}");
	break;
	case MessageSentEventArgs msgArgs:
	var msg = msgArgs.Message;
	Console.WriteLine($"[邮件通知] {msg.Sender.Name}给您发送了消息:{msg.Content}({(msgArgs.IsUrgent ? "紧急" : "普通")})");
	break;
	}
	}
	
	// 短信通知处理方法
	public void HandleSmsNotification(object sender, MessageSentEventArgs e)
	{
	if (e.IsUrgent) // 仅紧急消息发送短信
	{
	var receiver = e.Message.Receiver;
	Console.WriteLine($"[短信通知] 您收到{sender.GetType().Name}的紧急消息:{e.Message.Content},请立即查看!");
	}
	}
	
	// APP推送通知处理方法
	public void HandleAppPushNotification(object sender, EventArgs e)
	{
	if (e is MessageSentEventArgs msgArgs)
	{
	var receiver = msgArgs.Message.Receiver;
	Console.WriteLine($"[APP推送] 您有新消息来自{msgArgs.Message.Sender.Name} → {msgArgs.Message.Content.Substring(0, 10)}...");
	}
	}
	}
  1. 测试程序
    csharp
	class Program
	{
	static void Main(string[] args)
	{
	// 1. 创建实例
	var messageService = new MessageService();
	var notificationHandler = new NotificationHandler();
	
	// 2. 订阅事件
	// 登录事件订阅邮件通知
	messageService.OnUserLoggedIn += notificationHandler.HandleEmailNotification;
	// 消息发送事件订阅多个通知渠道
	messageService.OnMessageSent += notificationHandler.HandleEmailNotification;
	messageService.OnMessageSent += notificationHandler.HandleSmsNotification;
	messageService.OnMessageSent += notificationHandler.HandleAppPushNotification;
	
	// 3. 模拟用户登录(触发登录事件)
	var user1 = new User { Id = 1, Name = "张三", Email = "zhangsan@example.com", Phone = "13800138000", DeviceToken = "device_123" };
	messageService.UserLogin(user1);
	
	// 4. 模拟发送普通消息(触发消息事件)
	var user2 = new User { Id = 2, Name = "李四", Email = "lisi@example.com", Phone = "13900139000", DeviceToken = "device_456" };
	var message = new Message
	{
	Id = 1,
	Sender = user1,
	Receiver = user2,
	Content = "明天一起去图书馆吗?",
	SentTime = DateTime.Now
	};
	messageService.SendMessage(message);
	
	// 5. 模拟发送紧急消息(触发消息事件)
	var urgentMessage = new Message
	{
	Id = 2,
	Sender = user2,
	Receiver = user1,
	Content = "紧急:明天图书馆闭馆!",
	SentTime = DateTime.Now
	};
	messageService.SendMessage(urgentMessage, isUrgent: true);
	
	// 6. 取消订阅:移除短信通知
	messageService.OnMessageSent -= notificationHandler.HandleSmsNotification;
	Console.WriteLine("
=== 取消短信通知后,再次发送消息 ===");
	messageService.SendMessage(new Message
	{
	Id =3,
	Sender=user1,
	Receiver=user2,
	Content="收到,谢谢提醒!",
	SentTime=DateTime.Now
	});
	}
	}

逐行讲解

  1. 事件参数设计
    继承EventArgs:自定义事件参数需继承EventArgs(.NET事件设计规范),确保兼容性;
    传递上下文:MessageSentEventArgs包含消息对象、紧急状态等信息,让订阅者获取足够的事件上下文;
  2. 事件发布者(MessageService)
    事件定义:使用EventHandler泛型委托(T为事件参数),符合.NET标准;
    触发事件:OnUserLoggedIn?.Invoke(this, args)——?.避免空引用(无订阅者时不执行),Invoke传递事件源(this)和参数;
  3. 事件订阅者(NotificationHandler)
    多类型处理:HandleEmailNotification通过switch处理不同事件参数,实现通用通知;
    条件处理:HandleSmsNotification仅处理紧急消息,体现事件驱动的灵活性;
  4. 事件订阅与取消
    订阅:messageService.OnMessageSent += handler——绑定事件处理器;
    取消订阅:messageService.OnMessageSent -= handler——移除绑定,避免内存泄漏;
  5. 测试程序
    模拟场景:覆盖登录、普通消息、紧急消息、取消订阅等场景;
    结果验证:紧急消息触发短信通知,取消订阅后短信不再发送,验证事件机制的正确性。
    基础知识拓展
  6. 事件驱动核心思想
    发布-订阅模式:发布者(事件源)触发事件,订阅者(处理器)响应事件,组件解耦;
    实时响应:事件发生时立即通知,无需轮询(对比轮询:浪费资源、延迟高);
  7. .NET事件设计规范
    事件命名:用OnXXX(如OnMessageSent)表示事件;
    委托选择:优先使用EventHandler(T:EventArgs),避免自定义委托;
    参数传递:事件参数需继承EventArgs,传递事件上下文;
  8. 多播事件关键特性
    执行顺序:按订阅顺序执行事件处理器;
    异常处理:单个处理器抛出异常会中断后续执行(建议在处理器内捕获异常);
    取消订阅:必须保存处理器引用(如notificationHandler.HandleSmsNotification)才能取消;
  9. 异步事件处理
    问题:同步事件处理器阻塞主线程(如发送邮件耗时);
    解决方案:使用async void(仅用于事件处理器)或IAsyncEventHandler:
    csharp
	// 异步邮件通知处理器
	public async void HandleEmailNotificationAsync(object sender, EventArgs e)
	{
	if (e is MessageSentEventArgs msgArgs)
	{
	await SendEmailAsync(msgArgs.Message.Receiver.Email, msgArgs.Message.Content);
	}
	}
	// 订阅异步处理器
	messageService.OnMessageSent += HandleEmailNotificationAsync;

注意:async void的异常无法通过try-catch捕获,需在处理器内处理;

  1. 事件驱动vs轮询
特性 事件驱动 轮询
实时性 高(事件发生立即响应) 低(依赖轮询间隔)
资源消耗 低(无事件时无操作) 高(持续检查状态)
耦合度 低(发布者与订阅者解耦) 高(需直接访问状态)
适用场景 实时通知、系统告警 状态变化缓慢的场景

总结
本节通过实时消息通知系统,展示了事件驱动编程的核心实践:事件定义→订阅→触发→响应。事件驱动实现了组件解耦、实时响应,是构建高并发、低延迟系统的关键技术。
重点掌握:
.NET事件设计规范(EventHandler、EventArgs);
事件订阅/取消、触发的正确方式;
多播事件的异常处理与异步优化;
事件驱动是C#开发的必备技能,广泛应用于UI框架(如WPF、WinForms)、消息队列(如RabbitMQ)、实时系统(如IoT告警)等场景。

本站原创,转载请注明出处:https://www.xin3721.com/ArticlecSharp/c49425.html


相关教程