架构师_程序员_码农网

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 332|回复: 1

[资料] 【译】探索 .Net Reactive 响应式扩展中的主题

[复制链接]
发表于 2024-1-27 12:17:19 | 显示全部楼层 |阅读模式
.Net 反应式扩展为开发人员提供了一组功能来为 .Net 开发人员实现反应式编程模型,从而使用声明性操作使事件处理更简单且更具表现力。虽然反应式扩展的关键基石是 IObserver 和 IObservable 接口,但作为开发人员,您通常不需要自己实现这些接口。该库支持内置类型 Subject<T>  ,它实现了接口并支持许多函数。

主题是库中不同可用主题的基础,还有其他主题 -  ReplaySubject<T>、  BehaviorSubject<T> 和 AsyncSubject<T>。了解它们之间的本质区别以及如何使用它们来更好地利用该库非常有用。

在本文中,我们将比较 Subject<T> 及其同级对象,试图说明它们行为之间的差异。

Subject<T>

如前所述,  Subject<T> 是可用主题的基础,它提供了一种使用库的简单方法,而无需自己实现 IObservable<T> 和 IObserver<T> 接口。下面显示了主题类型的简单演示。

在上面的代码中,我们创建了一个 Subject<T>的实例 ,并且由于它实现了 IObserver<T> 和 IObserverable<T>,所以使用相同的实例来订阅并将值发布到IObserver。这里需要注意的另一个重要点是我们如何使用 Subscribe 方法的重载来接受操作作为输入。将为每个发布的值执行该操作,在本例中是将数字打印到控制台。

让我们尝试在下图中显示已发布的值和 IObserver(在此Action<T>中)打印到控制台的值 。这将帮助我们轻松比较剩余的兄弟姐妹和变体。

QQ截图20240127120629.jpg

第一行表示发布的值,第二行表示 IObserver 接收到的值。此外,我们还添加了一行来指示观察者在执行的哪个点订阅数据流。这条线由垂直虚线表示。

在上面的代码中,我们注意到观察者在发布第一个值之前订阅了数据流。图中所示为 订户 线放置在第一个元素之前。从输出行中可以看出,这对输出(此时)没有任何影响。

但是,如果观察者仅在某些值已经发布后才订阅数据怎么办?这会对观察者收到的数据产生影响吗?在查看输出之前,让我们首先编写相同的代码。

在上面的代码中,我们可以观察到只有在两个值(1和2)发布后,观察者才会订阅数据流。正如人们所预料的那样,这将导致观察者无法接收到在调用订阅方法之前发布的数据。如下图所示。

QQ截图20240127120712.jpg

如果您想读取所有已发布的值,即使观察者订阅较晚,该怎么办?这就是 ReplaySubject<T> 发挥作用的地方。

ReplaySubject<T>

ReplaySubject<T> 缓存值并为后期订阅者重播它们。这对于避免竞争条件很有用。让我们更改之前的代码以使用 ReplaySubject<T> 并看看它如何影响观察者接收到的内容。

如上面的代码所示,除了我们现在使用ReplaySubject<T> 而不是 subject<T>之外,代码几乎没有任何变化 。下图说明了对观察者接收到的数据的影响。

QQ截图20240127120830.jpg

如图所示,即使订阅者订阅较晚,缓存的值现在也会重播给订阅者。当然,这种有用的功能需要付出一定的代价。此实现将缓存订阅者发布的每个值,当数据量明显较大时,这可能会导致不良的内存问题。

然而,  ReplaySubject<T> 有不止一种方式解决该问题。为了这个示例,我们将研究两个示例,它们将使用大小和时间约束来限制缓存的值。

作为第一种情况,我们将使用缓存的大小来限制缓存的值。ReplaySubject<T>的构造函数  提供了一个重载,它接受一个整数,该整数表示缓存缓冲区的大小(最大元素计数)。在我们的示例中,让我们更改代码以将缓存大小限制为 1。

请注意我们如何使用ReplaySubject<T>的构造函数重载将 Cache 的大小提供为 1  。这限制了缓存并确保仅缓存一个元素,并且在发布后立即将其替换为新元素。更改的影响如下所示。

QQ截图20240127120920.jpg

限制缓存的另一种方法是限制缓存项目的时间,或者换句话说,为缓存的项目提供到期时间。

让我们编写代码来说明该示例。

与前面的代码类似,我们使用 ReplaySubject<T> 构造函数的重载来指定缓存中项目的到期时间。为了演示我们的案例,我们在值的发布之间引入了延迟。

由于观察者订阅之前需要整整 1200 毫秒,任何超过 1000 毫秒过期时间的元素都将从缓存中删除。在此示例中,这将导致值 1 从缓存中删除,并且不会重播给迟到的订阅者。如下图所示。

QQ截图20240127120959.jpg

ReplaySubject<T>还有其他重载  ,可以提供更大的灵活性并微调缓存的值,但为了举例,我们将保留上面已经介绍过的两个示例。

BehaviourSubject<T>

BehaviourSubject<T>与ReplaySubject<T> 非常相似  ,因为它有助于缓存值。但有一个显着的差异。 BehaviourSubject<T> 仅缓存最后发布的值。在进一步讨论这个问题之前,让我们先编写一些代码。

如果 BehaviorSubject<T> 仅缓存单个值(最后已知),那么它与 大小为1的ReplaySubject<T>有何不同 ?下面的示意图明确地反映了上面代码的情况。

QQ截图20240127121053.jpg

然而,这并不完全正确。这里有两个重要的区别需要理解。第一个是默认值的存在。请注意,在上面的代码中,我们在BehaviourSubject<T>的构造函数中提供了值 0 作为默认值 。如果缓存中不存在任何值(或者换句话说,在观察者订阅之前没有发布任何数据),则将返回默认值。这与大小为 1 的ReplaySubject<T>不同  ,后者没有任何值。下面的代码和序列的可视化表示演示了此行为。

QQ截图20240127121234.jpg

第二个区别是 BehaviorSubject<T> 和 ReplaySubject<T> 在订阅已完成的序列时的行为方式。完成后订阅时, BehaviorSubject  <T> 将不会有任何值,如下面的代码所示。

保证订阅者不会收到任何值,因为订阅是在完成后发生的。

QQ截图20240127121312.jpg

但是, ReplaySubject<T>就是这种情况 。不能保证观察者不会收到任何值,如下面的代码所示。

如上面的代码所示,缓存的大小为 1,即使在完成调用之后调用订阅,缓存也会保留(直到满足到期条件),因此在这种情况下将收到最后发布的值。

QQ截图20240127121433.jpg

AsyncSubject<T>

AsyncSubject<T>是我们将在本文中探讨的Subject<T>的最后一个同级,  它与前两个(ReplaySubject 和BehaviourSubject)非常相似,因为它也缓存结果。但再次存在显着差异。仅当序列被标记为完成时, AsyncSubject  <T> 才会发布最后一个缓存的值(它仅缓存一个值,即最后一个值)。

考虑以下代码。

这将为观察者生成一个值,即序列标记为完成之前发布的最后一个值 - 值 4。如下图所示。

QQ截图20240127121539.jpg

但是,如果我们跳过将序列标记为完成的调用,会发生什么情况呢?让我们注释掉该行并重试。

这不会为观察者生成任何数据,因为 AsyncSubject<T> 仅在序列标记为完成后才会发布结果。

QQ截图20240127121613.jpg

这是一个显着的差异,任何使用 AsyncSubject<T>的人 都应该记住这一点。

结论

本文演示了 Subject<T>的各个同级 及其一些变体之间的差异。了解这些细微的差异通常很有用,因为如果您没有意识到,它们可能会表现出与您预期不同的行为。

原文链接:https://www.c-sharpcorner.com/article/exploring-subject-t-in-reactive-extensions-for-net/





上一篇:.NET/C# 检查 TCP 端口是否可用
下一篇:NSIS(一)制作一个简单的安装程序
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
 楼主| 发表于 2024-1-27 12:19:47 | 显示全部楼层
Angular RxJS 之 Subject 主题订阅
https://www.itsvse.com/thread-9209-1-1.html
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

免责声明:
码农网所发布的一切软件、编程资料或者文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:help@itsvse.com

QQ|手机版|小黑屋|架构师 ( 鲁ICP备14021824号-2 )|网站地图

GMT+8, 2024-4-27 21:05

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表