你是否遇到过这样的情况:应用程序运行一段时间后内存占用越来越高,最终导致系统卡顿甚至崩溃?如果你的项目中大量使用了事件订阅,那么很可能就是事件订阅未正确取消导致的内存泄漏问题。
今天我将分享一个实用的C#事件订阅管理器,它能够自动管理所有事件订阅的生命周期,彻底告别手动取消订阅的烦恼。这个工具类不仅代码简洁,而且在实际项目中屡试不爽,堪称防止内存泄漏的利器!
在C#开发中,事件订阅导致的内存泄漏是最容易被忽视却又最致命的问题之一:
c#namespace AppEventSubscriptionManager
{
public class Order
{
public int OrderId { get; }
public string CustomerName { get; }
public DateTime OrderDate { get; }
public Order(int orderId, string customerName)
{
OrderId = orderId;
CustomerName = customerName;
OrderDate = DateTime.Now;
}
}
public class OrderCreatedEventArgs : EventArgs
{
public Order Order { get; }
public OrderCreatedEventArgs(Order order)
{
Order = order;
}
}
public class OrderService
{
public event EventHandler<OrderCreatedEventArgs> OrderCreated;
public void CreateOrder(Order order)
{
Console.WriteLine($"创建订单: {order.OrderId} for {order.CustomerName}");
OrderCreated?.Invoke(this, new OrderCreatedEventArgs(order));
}
}
public class NotificationService
{
public NotificationService(OrderService orderService)
{
// ⚠️ 危险:只订阅,不取消订阅
orderService.OrderCreated += OnOrderCreated;
}
private void OnOrderCreated(object sender, OrderCreatedEventArgs e)
{
Console.WriteLine($"通知: 订单 {e.Order.OrderId} 已创建,客户: {e.Order.CustomerName},日期: {e.Order.OrderDate}");
}
}
internal class Program
{
static void Main(string[] args)
{
// 创建订单服务和通知服务的实例
OrderService orderService = new OrderService();
NotificationService notificationService = new NotificationService(orderService);
Order newOrder = new Order(1, "张三");
orderService.CreateOrder(newOrder);
Order anotherOrder = new Order(2, "李四");
orderService.CreateOrder(anotherOrder);
}
}
}

你有没有想过,为什么ChatGPT能像人类一样自然地对话?为什么它能写诗、编程、甚至帮你分析复杂的商业问题? 很多人以为这只是简单的"关键词匹配"或"模板填充",但实际上,GPT背后的技术原理远比你想象的精妙。
今天,咱们就用最接地气的方式,把GPT这个看似高深的技术"掰开揉碎"讲清楚。读完这篇文章,你不仅能理解GPT的工作原理,还能向身边的朋友科普这项改变世界的技术。
GPT这个名字可不是随便起的,它是三个英文单词的缩写,每个字母都藏着关键信息:
这意味着模型具备"创造"能力——不是简单地检索现有内容,而是真正生成全新的文本。
在正式"上岗"之前,模型已经读过海量的书籍、网页、文章,掌握了语言的基本规律和常识。
这是一种革命性的神经网络架构,让机器能够理解复杂的上下文关系,就像人类阅读时能联系前后文一样。
听起来还是有点抽象?别急,咱们一个一个拆开来讲。

很多人误以为GPT只是在"复制粘贴"互联网上的内容。其实不然——它是通过预测概率来生成文本的。
想象你在跟朋友聊天,对方说了半句话:"今天天气真…",你的大脑会自动预测下一个词可能是"好"、"热"、"冷"。GPT做的就是同样的事,只不过它是基于数学概率来预测。
作为Windows下的Python开发者,你是否经常遇到这样的场景:老板给你一个复杂的Excel表格,要求批量处理数据、生成报表,或者需要定期更新Excel中的数据?手工操作不仅效率低下,还容易出错。
本文将带你深入掌握openpyxl这个强大的Excel操作库,从基础读写到高级应用,让你告别重复的Excel操作,实现真正的办公自动化。无论你是Python新手还是有一定经验的开发者,都能在这里找到实用的解决方案。
在众多Python Excel操作库中,为什么推荐openpyxl?让我们来看看实际场景:
传统方式的痛点:
openpyxl的优势:
首先安装必要的库:
bashpip install openpyxl pandas
pythonfrom openpyxl import Workbook
from openpyxl.utils import get_column_letter
# 创建新的工作簿
wb = Workbook()
ws = wb.active # 获取活动工作表
ws.title = "销售数据" # 设置工作表名称
# 写入数据
ws['A1'] = '产品名称'
ws['B1'] = '销售额'
ws['C1'] = '日期'
# 批量写入数据
data = [
['手机', 5000, '2024-01-01'],
['电脑', 8000, '2024-01-02'],
['平板', 3000, '2024-01-03']
]
for row_num, row_data in enumerate(data, start=2):
for col_num, value in enumerate(row_data, start=1):
ws.cell(row=row_num, column=col_num, value=value)
# 保存文件
wb.save('销售数据.xlsx')
print("✅ Excel文件创建成功!")

你是否曾经被客户要求开发一个酷炫的工业监控界面?或者想要在WinForms应用中实现流畅的动画效果?传统的GDI+绘图性能有限,而WPF又显得过于重量级。今天我们来探索一个完美的解决方案:SkiaSharp + WinForms,它能让你轻松实现60FPS的工业级动画效果。
本文将手把手教你构建一个完整的工业动画演示系统,包含齿轮转动、传送带、机械臂等多种动画效果,代码开箱即用!
在WinForms开发中,我们经常遇到这些问题:
c#// SkiaSharp:硬件加速 + 跨平台 + 开源免费
using SkiaSharp;
using SkiaSharp.Views.Desktop;
// 60FPS丝滑动画,告别卡顿
private Timer animationTimer = new Timer { Interval = 16 };
核心优势:
c#// 主窗体:FrmMain
public partial class FrmMain : Form
{
private SKControl skiaCanvas; // 绘图画布
private Timer animationTimer; // 动画定时器
private float rotationAngle = 0f; // 旋转角度
private float animationSpeed = 1.0f; // 动画速度
}
你会发现现在的C#项目或是Java也一样,打开代码后,他发现到处都是UserService、LoggingService、FileService等以"Service"结尾的类。作为.NET新手,他开始疑惑:这些"服务"到底是什么?有标准定义吗?
如果你也有同样的困惑,不用担心!不少C#开发者在职业生涯初期都被这个看似简单的概念困扰过。今天我们就来彻底搞清楚C#中"Service"的真正含义和最佳实践。
事实上,C#语言本身并没有定义"Service"。这更多是一种命名约定和架构设计模式,而不是语言特性。正如一位资深开发者所说:
"Service只是我们用来描述'做某件事'的类的词汇,与表示数据的类相对应。"
在不同上下文中,"Service"可能指代:

核心原则:Service负责行为(方法),Model负责数据(属性)
c#// 数据模型 - 只包含属性
public class Customer
{
public string Name { get; set; }
public string Email { get; set; }
public DateTime CreatedAt { get; set; }
}
// 服务类 - 包含业务逻辑行为
public class CustomerService
{
private readonly ICustomerRepository _repository;
public CustomerService(ICustomerRepository repository)
{
_repository = repository;
}
// 业务逻辑:验证并创建客户
public async Task<bool> CreateCustomerAsync(Customer customer)
{
// 验证逻辑
if (string.IsNullOrEmpty(customer.Email))
return false;
// 重复检查
var existing = await _repository.GetByEmailAsync(customer.Email);
if (existing != null)
return false;
// 设置创建时间
customer.CreatedAt = DateTime.UtcNow;
// 保存到数据库
await _repository.CreateAsync(customer);
return true;
}
}
⚠️ 常见坑点:新手容易把所有逻辑都塞进Controller,记住Controllers只负责HTTP请求处理!哈哈,好像Admin.net框架就是Controller+Service合一起了,说实话中小项目开发就是快。
c#// Repository:纯数据访问层
public interface IUserRepository
{
Task<User> GetByIdAsync(int id);
Task CreateAsync(User user);
Task UpdateAsync(User user);
}
// Service:业务逻辑层,使用Repository
public class UserService
{
private readonly IUserRepository _userRepository;
private readonly IEmailService _emailService;
public UserService(IUserRepository userRepository, IEmailService emailService)
{
_userRepository = userRepository;
_emailService = emailService;
}
// 复杂业务流程:用户注册
public async Task<RegistrationResult> RegisterUserAsync(RegisterRequest request)
{
// 1. 业务验证
if (!IsValidEmail(request.Email))
return RegistrationResult.InvalidEmail();
// 2. 检查重复
var existingUser = await _userRepository.GetByEmailAsync(request.Email);
if (existingUser != null)
return RegistrationResult.EmailExists();
// 3. 创建用户
var user = new User
{
Email = request.Email,
PasswordHash = HashPassword(request.Password),
CreatedAt = DateTime.UtcNow,
IsActive = false // 需要邮箱验证
};
await _userRepository.CreateAsync(user);
// 4. 发送验证邮件
await _emailService.SendVerificationEmailAsync(user.Email);
return RegistrationResult.Success(user.Id);
}
private bool IsValidEmail(string email) { /* 验证逻辑 */ }
private string HashPassword(string password) { /* 密码哈希 */ }
}
💡 金句总结:Repository管数据(这块有不少老程序师一时不习惯),Service管业务,Controller管请求.