You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#两种事件订阅方式差异及Binance.Net中Lambda订阅是否需手动取消

事件订阅写法差异及Lambda订阅取消规则

两种订阅方式的核心区别

  • 命名方法订阅(示例1):你声明了独立的PortfolioService_Exception方法作为事件处理逻辑,每次+=/-=操作的都是同一个方法对应的委托实例,操作完全可控,可以正常配对完成订阅和取消。
  • 匿名Lambda订阅(示例2):你直接写在+=后的Lambda表达式是运行时生成的临时委托实例,没有显式变量持有它的引用,哪怕你再写一行完全相同的Lambda代码,生成的也是不同的委托实例,因此无法直接通过-=匹配到之前注册的处理器。

Lambda订阅是否需要手动取消?

需要。只要完成了事件订阅,事件源(也就是你代码里的subscription.Data对象)就会持有处理器的引用:你的Lambda因为捕获了当前类的_logger成员,还会反向持有当前类的实例引用。如果不取消订阅,且subscription对象的生命周期长于你的服务类,会导致你的服务类无法被GC回收,出现内存泄漏。

但匿名Lambda无法直接用-=取消,有两种解决方式:

  1. 提前把Lambda存到委托变量中,订阅和取消都使用同一个变量:
// 声明委托变量持有Lambda引用
Action<Exception> exceptionHandler = ex => 
{
    _logger.LogInformation($"Error: {ex.StackTrace}");
};

// 订阅
subscription.Data.Exception += exceptionHandler;

// 取消订阅
subscription.Data.Exception -= exceptionHandler;
  1. 不需要单独取消事件的场景下,可以直接调用UpdateSubscription提供的CloseAsync()方法,该方法会关闭整个数据流订阅,底层会自动清理所有绑定的事件处理器,无需单独操作-=。

结合业务代码的补充提示

你当前代码中注册的匿名Exception处理器,只要在订阅生命周期结束时调用CloseAsync()关闭用户数据流,就不会出现内存泄漏问题。如果你会多次执行InitAsync()创建新的订阅,需要注意及时清理旧的订阅实例,避免资源泄漏。

内容的提问来源于stack exchange,提问作者nop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 21:27:03