在根 IObservable 的生命周期内将没有最终订阅者的“中间 IObservables”保留在内存中

2023-12-19

例如,考虑一下:

    public IDisposable Subscribe<T>(IObserver<T> observer)
    {
        return eventStream.Where(e => e is T).Cast<T>().Subscribe(observer);
    }

The eventStream是一个长期存在的事件源。生命周期较短的客户端将使用此方法订阅一段时间,然后通过调用取消订阅Dispose在返回的IDisposable.

然而,虽然eventStream仍然存在并且应该保存在内存中,有 2 个新的IObservables由该方法创建的 - 由Where()大概是保存在内存中的方法eventStream,以及由返回的Cast<T>()方法可能由返回的方法保存在内存中Where() method.

这些“中间 IObservables”(有更好的名字吗?)将如何清理?或者它们现在会在生命周期中存在吗?eventStream即使它们不再有订阅并且除了它们的来源之外没有其他人引用它们IObservable因此永远不会再有订阅?

如果通过通知父母他们不再订阅来清理它们,那么他们怎么知道没有其他东西引用它们并且可能在以后的某个时候订阅它们?


然而,虽然 eventStream 仍然存在并且应该保留在内存中,但此方法创建了 2 个新的 IObservables - 一个由Where() 方法返回,可能由 eventStream 保存在内存中,另一个由Cast() 方法可能由Where() 方法返回的方法保存在内存中。

你有这个落后。让我们回顾一下正在发生的事情的链条。

IObservable<T> eventStream; //you have this defined and assigned somewhere

public IDisposable Subscribe<T>(IObserver<T> observer)
{
    //let's break this method into multiple lines

    IObservable<T> whereObs = eventStream.Where(e => e is T);
    //whereObs now has a reference to eventStream (and thus will keep it alive), 
    //but eventStream knows nothing of whereObs (thus whereObs will not be kept alive by eventStream)
    IObservable<T> castObs = whereObs.Cast<T>();
    //as with whereObs, castObs has a reference to whereObs,
    //but no one has a reference to castObs
    IDisposable ret = castObs.Subscribe(observer);
    //here is where it gets tricky.
    return ret;
}

What ret是否有引用取决于各种可观察量的实现。从我在 Rx 库的 Reflector 和我自己编写的运算符中看到的情况来看,大多数运算符不会返回引用可观察运算符本身的一次性对象。

例如,一个基本的实现Where会是这样的(直接在编辑器中输入,没有错误处理)

IObservable<T> Where<T>(this IObservable<T> source, Func<T, bool> filter)
{
    return Observable.Create<T>(obs =>
      {
         return source.Subscribe(v => if (filter(v)) obs.OnNext(v),
                                 obs.OnError, obs.OnCompleted);
      }
}

请注意,返回的一次性将通过创建的观察者引用过滤器函数,但不会引用Where可观察到的。Cast可以使用相同的模式轻松实现。本质上,操作员成为观察者包装工厂。

所有这些对当前问题的影响是中间 IObservables 有资格进行垃圾收集在方法结束时。过滤函数传递给Where只要订阅存在,就会一直存在,但是一旦订阅被处置或完成,仅eventStream仍然存在(假设它还活着)。

EDIT对于 supercat 的评论,让我们看看编译器如何重写它,或者如何在没有闭包的情况下实现它。

class WhereObserver<T> : IObserver<T>
{
    WhereObserver<T>(IObserver<T> base, Func<T, bool> filter)
    {
        _base = base;
        _filter = filter;
    }

    IObserver<T> _base;
    Func<T, bool> _filter;

    void OnNext(T value)
    {
        if (filter(value)) _base.OnNext(value);
    }

    void OnError(Exception ex) { _base.OnError(ex); }
    void OnCompleted() { _base.OnCompleted(); }
}

class WhereObservable<T> : IObservable<T>
{
    WhereObservable<T>(IObservable<T> source, Func<T, bool> filter)
    {
        _source = source;
        _filter = filter;
    }

    IObservable<T> source;
    Func<T, bool> filter;

    IDisposable Subscribe(IObserver<T> observer)
    {
        return source.Subscribe(new WhereObserver<T>(observer, filter));
    }
}

static IObservable<T> Where(this IObservable<T> source, Func<T, bool> filter)
{
    return new WhereObservable(source, filter);
}

您可以看到观察者不需要对生成它的可观察对象进行任何引用,并且可观察对象也不需要跟踪它创建的观察者。我们甚至没有创建任何新的 IDisposable 来从我们的订阅中返回。

实际上,Rx 有一些用于匿名可观察/观察者的实际类,它们接受委托并将接口调用转发给这些委托。它使用闭包来创建这些委托。编译器不需要生成实际实现接口的类,但翻译的精神保持不变。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在根 IObservable 的生命周期内将没有最终订阅者的“中间 IObservables”保留在内存中 的相关文章

  • 切换图片框可见性 C#

    为什么图片框控件的可见性属性在这里不起作用 我最初将它们设置为 false 以便在屏幕加载时它们不可见 但后来我想切换这个 我已完成以下操作 但似乎不起作用 这是一个 Windows 窗体应用程序 private void Action w
  • C# 中的协变和逆变

    首先我要说的是 我是一名正在学习 C 编程的 Java 开发人员 因此 我会将我所知道的与我正在学习的进行比较 我已经使用 C 泛型几个小时了 我已经能够在 C 中重现我在 Java 中知道的相同内容 除了几个使用协变和逆变的示例 我正在读
  • 使用不带参数的 Split() 时,默认分隔符是什么?

    所以我看了看String Split 今天 C 中的方法 我意识到你也可以向它传递零参数 这是我从未考虑过的 使用时默认的分隔符是什么Split 没有任何参数 如果没有值 则为空白 来源自here https msdn microsoft
  • 如何将pdf页面设置设置为打印属性对话框?

    大家好 我想知道如何设置 pdf 页面设置到打印属性对话框 例如 如果我的 PDF 页面设置为横向 则布局会自动显示横向而不是纵向 如果我的 PDF 页面设置为纵向 则布局会自动显示纵向 我在这个主题上做了很多研发 但没有找到任何满意的链接
  • 返回 int& 的函数[重复]

    这个问题在这里已经有答案了 我在网上查了一下发现一篇试图解释的文章std move和右值 http thbecker net articles rvalue references section 01 html并发现了一些我实在无法掌握的东
  • 如何使用汇编获取BIOS时间?

    我正在从头开始实现一个小型操作系统 用于教育目的 现在 我想使用汇编来获取 BIOS 时间 我对此进行了很多搜索 但找不到任何代码示例来执行此操作 如果有人可以提供任何参考或代码示例或与此相关的任何内容 我将非常感激 See 时钟中断 1a
  • 抽象类或接口。哪种方式是正确的?

    有两种方法可以选择抽象类或接口 微软解决方案和Oracle解决方案 微软 设计指南 请使用抽象 在 Visual Basic 中为 MustInherit 类而不是接口来将协定与实现分离 http msdn microsoft com en
  • 如何使用泛型类型的 DataContractSerializer 编写自定义序列化器?

    我想编写一个自定义序列化器 用于将会话状态存储到Azure 缓存 预览版 这意味着这个自定义序列化器必须实现IDataCacheObjectSerializer 如果我错了 请告诉我 我需要编写这个自定义序列化程序的原因是我需要序列化一些包
  • 指示泛型返回动态类型的对象

    这个问题是我原来问题的后续问题here https stackoverflow com questions 2541184 using a type object to create a generic 假设我有以下泛型类 简化 class
  • 在“using”语句中使用各种类型 (C#)

    自从C usingstatements只是try finally dispose 的语法糖 为什么它接受多个对象仅当它们属于同一类型时 我不明白 因为它们需要的只是 IDisposable 如果它们都实现 IDisposable 应该没问题
  • 使用scanf()时如何区分整数和字符

    我只是使用该功能scanf 代码如下 scanf d a printf d a 当我输入1时 它会像我想要的那样打印1 但即使我输入 1a 它也会像以前一样打印 1 当用户输入非整数时 例如 2 3 12ab 1 a 我想向用户显示 输入整
  • C# 中处理 SQL 死锁的模式?

    我正在用 C 编写一个访问 SQL Server 2005 数据库的应用程序 该应用程序是数据库密集型的 即使我尝试优化所有访问 设置适当的索引等 我预计迟早会遇到死锁 我知道为什么会发生数据库死锁 但我怀疑我能否在某个时候发布不发生死锁的
  • 从包含大量文件的目录中检索文件

    我的目录包含近 14 000 000 个 wav 格式的音频样本 所有普通存储 没有子目录 我想循环浏览文件 但是当我使用DirectoryInfo GetFiles 在该文件夹上 整个应用程序冻结了几分钟 可以用另一种方式完成吗 也许读取
  • 如何将字符串转换为 Indian Money 格式?

    我正在尝试将字符串转换为印度货币格式 例如如果输入为 1234567 则输出应为 12 34 567 我编写了以下代码 但它没有给出预期的输出 CultureInfo hindi new CultureInfo hi IN string t
  • 是什么原因导致 Linq 错误:此方法无法转换为存储表达式?

    我有一堆具有相同 select 语句的 Linq to Entity 方法 所以我想我会很聪明 并将其分离到它自己的方法中以减少冗余 但是当我尝试运行代码时 我得到了以下内容错误 该方法不能转化为 商店表达式 这是我创建的方法 public
  • 我应该如何在 VB.NET 中进行转换?

    所有这些都相等吗 在什么情况下我应该选择其中一个而不是其他 var ToString CStr 变量 CType 变量 字符串 DirectCast 变量 字符串 编辑 来自的建议不是我自己 https stackoverflow com
  • asp.net c# 防止在从服务器端代码更改索引时触发 selectedindexchanged 事件

    我在同一个 aspx 页面上有两个下拉列表控件
  • 理解 C++11 中的 std::atomic::compare_exchange_weak()

    bool compare exchange weak T expected T val compare exchange weak 是 C 11 中提供的比较交换原语之一 它是weak即使对象的值等于 它也会返回 falseexpected
  • 如何将 CSV 文件读入 .NET 数据表

    如何将 CSV 文件加载到System Data DataTable 根据CSV文件创建数据表 常规 ADO net 功能是否允许这样做 我一直在使用OleDb提供者 但是 如果您正在读取具有数值的行 但希望将它们视为文本 则会出现问题 但
  • 如何使用 ASP.NET Web 表单从代码隐藏中访问更新面板内的文本框、标签

    我在更新面板中定义了一些控件 它们绑定到中继器控件 我需要根据匿名字段隐藏和显示用户名和国家 地区 但问题是我无法以编程方式访问更新面板中定义的控件 我如何访问这些控件 我也在网上查找但找不到很多参考资料 下面是来自aspx页面和 cs页面

随机推荐

  • iPad/iPhone 上 CSS 提交按钮奇怪的渲染

    我注意到 如果我使用 CSS 使用半径 颜色和边框来设计按钮的样式 它们看起来不错 但在 iphone ipad ipod 中它们看起来很糟糕 不应该与 Safari 桌面中的渲染相同吗 哎呀 我刚刚自己发现了这个 只需将此行添加到您需要的
  • 无法在 Eclipse 中引用 jdbc.SQLServerDriver (ClassNotFoundException)

    我正在尝试使用 JDBC 的 MSSQL 驱动程序 我已按照有关如何将外部 JAR 文件添加到 Eclipse Windows IDE 的说明进行操作 如下所示 从这里下载安装http msdn microsoft com en us sq
  • 如何验证 SMTP 服务器

    我正在开发一个项目 我必须验证给定的 SMTP 服务器 即用户在文本框中提供详细信息 然后单击测试按钮 我想检查用户输入的服务器是否是Smtp服务器 任何想法 您可能希望通过适当的异常处理来改进此快速代码 并且还可能设置超时 如果无法连接
  • 在 typedef 结构体上使用 sizeof 运算符

    这可能是太明显的事情了 然而 尽管许多 stackoverflow 线程讨论了这个问题的不同方面 但我找不到具体的答案 typedef struct tmp unsigned int a unsigned int b tmp int mai
  • 平面图内的 rxjs 条件

    我想在 flatMap 中有一个条件来检查第一个可观察值返回的内容 如果不满足条件 我想中断并导航到不同的页面 this service getData id flatMap data gt if data return Observabl
  • 如何创建常见的 xsd 生成的 java 类

    我想生成java课程通过XSDs 我想使用 包括一个XSD文件在另一个文件中 但是当我将它们包含在另一个文件中时XSDs same java两个包中都会生成类 我也在使用maven jaxb2 plugin plugin Do 单独 又名模
  • Windows 7 中的时钟如何工作?

    我在某处读过这个答案 但我不太明白 我了解Windows每次curTimeIncrement都会增加时钟 156001 100 纳秒 与 curTimeAdjustment 的值 156001 N 但是 当使用 GetSystemTime
  • 将 PHP 项目从 Git 部署到未安装 Git 的服务器

    我需要找到一种将存储在 git 存储库中的 PHP 项目部署到临时和生产服务器的方法没有安装git 到目前为止我发现的脚本 即 Capistrano 需要目标服务器上的 Git 不幸的是 我的主机不允许这样做 到目前为止唯一的方法是通过标准
  • CSS“位置:固定”:移动缩放

    我正在尝试解决移动浏览器上的 css position fixed 属性问题 我有一个固定的div div other content here div 与CSS logo position fixed webkit backface vi
  • 如何创建加起来等于特定数字的数字列表

    我需要一些帮助 在 Prolog 中编写一个谓词 给定一个数字作为输入 返回一个列表列表 其中的数字相加 让我们调用谓词添加列表 2 它应该像这样工作 addUpList 3 P P 1 2 2 1 1 1 1 expected resul
  • 如何保存所有 Docker 镜像并复制到另一台机器

    我的系统上有以下图像列表 并且想要将所有这些图像复制到远程计算机 REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE u14 py269 latest 6a1ec0b508b3 4 days ago 8
  • 实体设计器缺失

    正如标题所示 不知何故 实体设计器从我安装的 Visual Studio 2010 中消失了 当尝试打开 edmx 文件时 它仅在 XML 编辑器中打开它 当我选择 打开方式 时 实体设计器不会显示在列表中 它以前有用过 但我不知道我可以做
  • ViewBinding - 不同风格的布局资源

    我的风格包含与我的布局资源相同的布局资源main源集 这样一来 它就会用特定风味的风味覆盖主要风味 我在很多地方都这样做过并且效果很好 直到我介绍ViewBinding 为了准确起见 布局是 包含 在片段中的嵌套布局 结构如下 main r
  • 没有任何改变,但 eclipse egit 将文件标记为已更改

    我正在使用 eclipse egit 和 github 我发现了一些奇怪的事情 我没有更改任何内容 但 egit 将文件标记为 已更改 看图片 文件 run bat 被标记为 已更改 与 Git索引中的文件 相比 你可以看到没有什么不同 与
  • 读取注释行以“##”开头的表格

    我正在努力使用 R 读取变体调用格式 VCF 的表格 每个文件都有一些以以下开头的注释行 然后是标题开头 contig
  • 如何从数据框中的列中减去具有唯一行的值

    很难用标题来解释这个问题 但这里我有一个数据框 你可以看到我有 3 个流名称 我有 3 个与每个流名称关联的唯一值 我希望从在中找到的相应流的值中减去这些唯一值value列 然后附加到标题为新列的数据框中error stream n rat
  • Git 不会忽略 .gitignore 中的某些 Xcode 文件

    我是 Git 新手 我正在使用它来备份我正在处理的 iPhone 项目 我添加了更新时 Git 应忽略的文件列表 xcode 文件 但是当我提交更改时 此 perspectivev3 位于我的 gitignore 中 文件不断显示 有谁知道
  • Spring中的策略模式和依赖注入

    我有一个Strategy接口 它的实现是策略A and 策略B 两者都定义为 成分的 他们有一个 Autowired属性也是如此 我该如何根据字符串值获取其中之一的实例 这是我的控制器的操作 应该执行该策略 RequestMapping b
  • 在登录时从 Azure Active Directory 生成环回用户(反应本机应用程序)的最佳实践是什么?

    我有一个带有expo sdk的react native应用程序 使用loopback 3作为我的后端 我试图向其中添加Azure Active Directory授权和身份验证 以便我的用户可以使用他们的工作电子邮件和密码登录 我正在考虑如
  • 在根 IObservable 的生命周期内将没有最终订阅者的“中间 IObservables”保留在内存中

    例如 考虑一下 public IDisposable Subscribe