如何实现一个“更好”的Finally Rx操作符?

2024-04-27

最近我意识到 RxFinally https://learn.microsoft.com/en-us/previous-versions/dotnet/reactive-extensions/hh212133(v=vs.103)操作符的行为方式至少对我来说是出乎意料的。我的期望是抛出的任何错误finallyAction将传播到下游运营商的观察者。可惜事实并非如此。现实中运营商first将先行序列的完成(或失败)传播给其观察者,并且then调用action,在不可能传播操作引发的潜在错误的时间点。所以它会抛出错误ThreadPool,并使进程崩溃。这不仅出乎意料,而且存在很大问题。下面是此行为的最小演示:

Observable
    .Timer(TimeSpan.FromMilliseconds(100))
    .Finally(() => throw new ApplicationException("Oops!"))
    .Subscribe(_ => { }, ex => Console.WriteLine(ex.Message),
        () => Console.WriteLine("Completed"));

Thread.Sleep(1000);

结果:未处理的异常(Fiddle https://dotnetfiddle.net/o89QpE)

抛出的异常Finallylambda 不由Subscribe:onError处理程序,因为这是可取的。

这个功能(我很想称其为缺陷)严重限制了该功能的实用性Finally我眼中的运营商。本质上,我只能在我想要调用一个预计永远不会失败的操作时使用它,如果它失败,则表明应用程序状态发生灾难性损坏,并且无法恢复。我可以用它来举例Release a SemaphoreSlim(就像我所做的那样here https://stackoverflow.com/questions/64841312/how-to-merge-multiple-observables-with-order-preservation-and-maximum-concurrenc/64880836#64880836例如),只有当我的代码有错误时才会失败。在这种情况下我的应用程序崩溃是可以接受的。但我也用过recently https://stackoverflow.com/questions/69799279/is-it-possible-to-use-rx-using-operator-with-iasyncdisposable/69801283#69801283调用调用者提供的未知操作,该操作可能会失败,并且在这种情况下使应用程序崩溃是不可接受的。相反,错误应该传播到下游。所以我在这里问的是如何实现Finally变体(我们称之为FinallySafe)具有相同的签名,并且行为如下:

public static IObservable<TSource> FinallySafe<TSource>(
    this IObservable<TSource> source, Action finallyAction);
  1. The finallyAction应该被调用after the source序列已发出OnCompleted or an OnError通知,但是before该通知被传播给观察者。
  2. If the finallyAction调用成功完成,原来的OnCompleted/OnError通知应传播给观察者。
  3. If the finallyAction调用失败,OnError通知应该传播给观察者,其中包含刚刚发生的错误。在这种情况下,前一个错误可能导致source完成失败,应被忽略(不传播)。
  4. The finallyActionFinallySafe在完成之前取消订阅source。当订阅者(观察者)处置订阅时,finallyAction应该同步调用,并且任何错误都应该传播给调用者Dispose method.
  5. If the FinallySafe被多个观察者订阅,finallyAction应遵循上述规则,为每个订阅者独立地为每个订阅者调用一次。并发调用是可以的。
  6. The finallyAction每个订阅者不应被多次调用。

验证:替换FinallyFinallySafe在上面的代码片段中,应该会导致程序不会因未处理的异常而崩溃。

选择:我也愿意接受一个答案,它可以合理解释为什么内置函数的行为Finally操作员的行为优于自定义的行为FinallySafe运算符,如上所述。


Finally在序列结束后被调用,并且由于 Rx 合约只允许一个OnError or OnCompleted它不能发出第二个。

但是,如果你更换Finally with Do你可以获得你想要的行为。

试试这个代码:

Observable
    .Timer(TimeSpan.FromMilliseconds(100))
    .Do(_ => { }, () => throw new ApplicationException("Oops!"))
    .Subscribe
        (_ => { },
        ex => Console.WriteLine(ex.Message),
        () => Console.WriteLine("Completed"));

Thread.Sleep(TimeSpan.FromMilliseconds(1000));

这将按照您的预期运行。

我得到这个输出:

Oops!

如果您想在取消订阅时运行某些内容,请使用以下扩展方法:

public static class Ext
{
    public static IObservable<T> Unsubscribed<T>(this IObservable<T> source, Action unsubscribed) =>
        Observable.Create<T>(o =>
            new CompositeDisposable(source.Subscribe(o), Disposable.Create(unsubscribed)));
}

下面是它的使用示例:

var source = Observable.Never<int>();

var subscription =
    source
        .Unsubscribed(() => Console.WriteLine("Unsubscribed"))
        .Subscribe();

subscription.Dispose();

输出:

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

如何实现一个“更好”的Finally Rx操作符? 的相关文章

  • 我的 std::hash for std::tuples...有什么改进吗? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 有些人可能已经注意到 std hash 不支持元组 所以我添加了一个重载 它看起来比我到目前为止看到的解决方案 更好 有人有进一步减少这段代码的
  • Boost MPI 在监听列表时不会释放资源?

    这是一个后续问题如何释放 boost mpi request https stackoverflow com questions 44078901 how do i free a boostmpirequest 我在监听列表而不是单个项目时
  • C# 异步任务比同步慢

    你知道为什么同步斐波那契方法比异步 等待更快并且比异步任务更快吗 我在每个项目方法上都使用了异步 所以主要是这是一个非常糟糕的方法 Code static int FibonacciSync int number if number 0 r
  • 信号与信号2

    我的应用程序可能会受益于使用 boost 的信号库之一而不是本土解决方案 该应用程序是多线程的 但执行信号处理的部分是单线程的 如果多线程不是问题 是否有任何理由更喜欢 Boost Signals2 而不是 Boost Signal Boo
  • 如何使用c#从数据桶中获取所有文档?

    如何获取数据桶中的所有文档 我尝试过一个示例 但我只能获得一个特定的文档 这是我的代码 CouchbaseClient oclient oclient new CouchbaseClient vwspace data bucket name
  • C# 中 PKCS11Interop 库的线程安全使用 [已关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在使用 PKCS11Interop 在 HSM 内执行密钥管理操作 我使用的 HSM 是 Thales PCI Express 下面是
  • 我可以将 char 或 DateTime 设置为 null 吗?

    我可以将 null 设置为char数据类型 并且DateTime在 C 中 多谢你们 这是不可能的 它是一个值类型 使用 char myChar null DateTime myDate null 这相当于 Nullable
  • 为什么 BinaryFormatter 可以序列化 Action<> 但 Json.net 不能

    尝试序列化 反序列化 Action 尝试我的 1天真 JsonConvert SerializeObject myAction JsonConvert Deserialize
  • 如何调试.NET Windows Service OnStart方法?

    我用 NET 编写的代码仅在作为 Windows 服务安装时才会失败 该故障甚至不允许服务启动 我不知道如何进入 OnStart 方法 如何 调试 Windows 服务应用程序 http msdn microsoft com en us l
  • 检测反射 DLL 注入

    在过去的几年中 恶意软件 以及一些渗透测试工具 如 Metasploit 的 meterpreter 负载 已经开始使用反射 DLL 注入 PDF http www harmonysecurity com files HS P005 Ref
  • 检查两个函数或成员函数指针的签名是否相等

    我编写了一些代码来检查自由函数的签名是否等于成员函数的签名等 它比较提取的返回类型和函数参数 include
  • 列表到优先队列

    我有一个 C 大学编程项目 分为两个部分 在开始第二部分时应该使用priority queues hash tables and BST s 我 至少 在优先级队列方面遇到了麻烦 因为它迫使我自己重做第一部分中已经实现的许多代码 该项目是关
  • 冒号在c中起什么作用?

    我在课堂上得到了这个例子 但我不确定它的作用 我知道冒号添加了一个位字段 但我仍然不确定这个问题 a b gt 0 3 1 运算符称为条件运算符 If b值为 gt 0 价值3被分配给a否则值1被分配给a 以 Kernighan Ritch
  • 如果finally 块包含await,为什么*有时*不会在ThreadAbortException 上执行?

    UPDATE 我不认为这个问题是重复的ThreadAbortException最后可以跳过吗 https stackoverflow com questions 18002668 can threadabortexception skip
  • 应在堆栈上分配的最大数量

    我一直在寻找堆栈溢出有关应在堆栈上分配的最大内存量的指南 我看到了堆栈与堆分配的最佳实践 但没有关于应该在堆栈上分配多少以及应该在堆上分配多少的指南 有什么想法 数字可以作为指导吗 什么时候应该在堆栈上分配 什么时候应该在堆上分配 多少才算
  • 从具有相同属性的另一个对象创建对象

    我有一个 C 对象 可以说有 20 个属性 它是数据契约的一部分 我还有另一个具有类似属性的业务实体 我想从响应对象中填充该实体 除了将一个对象的每个属性分配给另一个对象的相应属性之外 还有其他方法可以做到这一点吗 是的 看看自动映射器 h
  • 在 C# 命令行应用程序中包含并执行 EXE

    所以我找到了一个很棒的小 EXE 命令行应用程序 我们将其称为 program exe 它输出一些我想用 C 操作的数据 我想知道是否有一种方法可以将program exe 打包 到我的Visual Studio项目文件中 这样我就可以将编
  • 实体框架读取列但阻止其更新

    给定一个数据库表 其中有一列包含历史数据但不再填充 实体框架中是否有一种方法可以读取该列 但在使用相同的模型对象时防止它被更新 例如我有一个对象 public class MyObject public string CurrentData
  • 如何通过代理将套接字连接到http服务器?

    最近 我使用 C 语言编写了一个程序 用于连接到本地运行的 HTTP 服务器 从而向该服务器发出请求 这对我来说效果很好 之后 我尝试使用相同的代码连接到网络上的另一台服务器 例如 www google com 但我无法连接并从网络中的代理
  • Apache Flink - “keyBy”中的异常处理

    由于代码错误或缺乏验证 进入 Flink 作业的数据可能会触发异常 我的目标是提供一致的异常处理方式 我们的团队可以在 Flink 作业中使用这种方式 而不会导致生产中出现任何停机 重启策略似乎不适用于此处 因为 简单的重启无法解决问题 我

随机推荐

  • 诊断 Mac OS X 上的堆碎片?

    我正在编写的核心基础应用程序似乎消耗的内存比我实际分配的内存多 根据活动监视器中的 真实内存 计数 我已通过 Instruments 中的 实时字节分配 视图确认我的实际分配符合我的预期 大约 10MB 但活动监视器中的 真实内存 计数显示
  • 轻松安全AppiumService

    我是 Appium 新手 我想使用 Appium 和 C 执行一些 ADB 命令 执行 adb shell ps 的示例 Dictionary
  • 如何延迟forkJoin

    你会怎样拖延 forkJoin 在 rxjs 中 这是我已经拥有但想使用的delay https www learnrxjs io operators utility delay html运营商用那个 return forkJoin thi
  • iOS 内存警告发送到已释放的 UIViewController

    我有奇怪的行为 我的应用程序正在启动UINavigationController 如果我推视图控制器ANavigationController 返回并模拟内存警告一切正常 如果我推相同的视图控制器 ANavigationController
  • 浮点数的最佳中点公式是什么?

    第一个公式 m a b 2 简单 但是存在很大的溢出风险 除了 数值分析 第 9 版伯登和费尔斯指出 当 b a 接近机器的最大精度时 a b 2 有可能返回一个在区间 a b 中不均匀的中点 尽管没有提供进一步的解释 第二个 m a b
  • 如何通过 Angular 6 中的服务将对象发送到不相关的组件?

    所以我是 Angular 的新手 我正在尝试使用服务将对象从组件 1 发送到组件 2 当我将结果记录到 component2 中的控制台时 它没有给我对象的更新值 这可能是因为服务在第二个组件中重新初始化 你能帮忙解决这个问题吗 这是我的代
  • 为什么“(def 元音?(set“aeiou”))”有效?

    我正在看优秀的 Clojure 教程here http ociweb com jnb jnbMar2009 html 在其中一个示例中 它具有如下所示的 Clojure 代码 def vowel set aeiou 这使得元音对于元音返回
  • 如何在vim中的相同行数前面插入多行?

    假设我有两个文本块 其中之一在我的剪贴板中 one two three 另一个位于我正在 vim 中编辑的文件中 AAA BBB CCC 如何在第二个块前面插入第一个块以获得以下结果 oneAAA twoBBB threeCCC 我希望有一
  • html5 下载属性在 FF 中不起作用

    您好 我有一个带有下载属性的锚标记 单击该标记时将从 href 中定义的 url 下载图像 这在 Chrome 中工作正常 但在 Firefox 中它需要浏览器中的图像 有什么办法可以让我们在 FF 中实现这一点吗 a href https
  • BlazorNotifyAuthenticationStateChanged 不会更新基于授权的元素

    我正在实施一个自定义AuthenticationStateProvider并在 mainLayout 中使用来自用户声明的信息 据我了解执行后NotifyAuthenticationStateChanged方法本身应该重新渲染所有使用的组件
  • 带有图像或路径的自定义滑块

    我的 WP7 应用程序中有一个滑块 我想重新设计它的样式 我的默认模板有问题 我做了类似的事情 但我无法将拇指 绑定 到该值
  • R 中独立环境的源脚本,而不是全局环境

    有没有办法source 一个脚本在R这样它就作为父环境附加到全局环境 GlobalEnv 目前 当我获取脚本时 该脚本的所有变量和函数都会出现在我的全局 交互式 环境中 我想将这些变量和函数包含在搜索路径中 但不包含在 GlobalEnv
  • Mockito-thenReturn(true) 仍然在模拟对象上返回 false

    我最近开始阅读有关 Mockito 的内容 根据我的理解 以下代码行必须返回 true 但它返回 false 测试班 public class PersonServiceImplTest Car car InjectMocks CarSer
  • 如何检测 JavaScript 中的哈希值后 URL 是否已更改

    如何在 JavaScript 中检查 URL 是否已更改 例如 像 GitHub 这样使用 AJAX 的网站将在 符号后附加页面信息 以创建唯一的 URL 而无需重新加载页面 检测此 URL 是否发生变化的最佳方法是什么 Is the on
  • 何时何地获取腕表复杂功能的数据

    经过几天的复杂工作后 我有信心对按规定间隔发生的更新的更新过程进行以下说明 The system calls requestedUpdateDidBegin This is where you can determine if your d
  • 用户 postgres 启动进程使所有 CPU 达到 100% 使用率

    用户 postgres 正在运行一个进程 该进程在 centos 机器上以 100 使用率占用所有 CPU postgresql 服务未运行 因此它不能是查询 当我尝试停止该进程时 它会自行重新启动 然后进程的名字就有点奇怪了 恭喜 通过将
  • 在 swift 中将参数传递给 #selector 方法[重复]

    这个问题在这里已经有答案了 我想在单击图像时将多个参数传递给函数 这是我的代码 var param1 120 var param2 hello var param3 world let image UIImage UIImage named
  • 为什么Go中可以在多个return语句中重新定义err

    考虑下面的示例来说明这个问题 它只是为了解释这个问题而构建的 但我在书中以及实际项目中都看到了类似的代码 package main import strconv fmt log func main n1 err strconv Atoi 1
  • 小部件预览图像

    My app preview image looks like this 我怎样才能让它看起来像 WhatsApp 聊天预览 小有阴影 我手机中的其他应用程序也使用相同类型的预览 我的小部件 xml
  • 如何实现一个“更好”的Finally Rx操作符?

    最近我意识到 RxFinally https learn microsoft com en us previous versions dotnet reactive extensions hh212133 v vs 103 操作符的行为方式