无扩展燕子从OnNext()呼吁一个线程池线程异常? [英] Reactive Extensions swallows exceptions from OnNext() called on a thread pool thread?

查看:211
本文介绍了无扩展燕子从OnNext()呼吁一个线程池线程异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用的Rx 2 .NET 4.5。当下面的代码运行时,它只是静静地退出不执行OnCompleted委托或显示任何错误。如果我使用 Scheduler.CurrentThread ToObservable ,它至少会抛出错误并终止程序,在这一点不执行OnCompleted有道理。但是,当这不是主要的一个以外的线程中执行,这种行为似乎不合理的和不可接受的。难道我错过了什么?



 静态无效的主要()
{
Enumerable.Range(0,1 )
.ToObservable(Scheduler.Default)
.Subscribe(O => {抛出新的异常(嗒嗒);},()=> Console.WriteLine(已完成));

Thread.sleep代码(2000);
}



编辑:
是的,当运行作为控制台应用程序,它总是会抛出错误,无论什么线程观察执行上。



然而,当我运行此代码在NUnit的测试作为如下,它2秒(线程睡眠时间)没有任何错误或消息(预期已完成)后自行退出。因此,它实际上是NUnit的导致该问题的?



  [的TestFixture] 
类节目
{
〔测试]
公共无效测试()
{
Enumerable.Range(0,1)
.ToObservable(Scheduler.Default)
.Subscribe($ b $博=> {抛出新的异常(嗒嗒);}
()=> Console.WriteLine(已完成));
Thread.sleep代码(2000);
}
}


解决方案

接收不赶观察员抛出的异常。这是一个已经长之前已经讨论了很重要的设计原则,但由于某种原因,它只是作为一些的6.4节中的接收设计准则




注意:不保护到电话的订阅的Dispose OnNext 的OnError 的和的 OnCompleted 的方法。这些电话都在单子的边缘。调用的的OnError 的从这些地方的方法会导致意外的行为。




从本质上讲,该指南将确保,从观察者的角度来看,的的OnError 将仅通过从可观察到的本身始发异常,包括直接在计算(而不是仅仅观察结果),该参加到用户代码的任何呼叫被调用。如果不是这种情况,那么观察者可能无法分辨的异常是否通过为的OnError 在他们的 OnNext 的处理程序,或在观察到的错误可能是一个错误



但更重要的是,它还可以确保通过的 OnNext 的处理程序抛出的任何异常得不到处理。这使得它更容易调试你的程序,保护用户数据。



话虽这么说,为什么你会观察不同的行为的原因,当 OnNext 在池线程中执行简直就是您的调试经验的结果。尝试启用首次机会异常的。



此外,我还通过更改 Thread.sleep代码 Console.ReadKey()避免竞争状态。


I use Rx 2 in .Net 4.5. When the following code runs, it just exits silently without executing the OnCompleted delegate or showing any errors. If I use Scheduler.CurrentThread in ToObservable, it will at least throw the error and terminate the program, at which point not executing OnCompleted makes sense. But when this is executed in a thread other than the main one, this behavior seems unreasonable and unacceptable. Do I miss anything?

static void Main()
{
     Enumerable.Range(0, 1)
                           .ToObservable(Scheduler.Default)
                           .Subscribe(o => { throw new Exception("blah"); }, () => Console.WriteLine("completed"));

     Thread.Sleep(2000);
 }

Edited: Yes, when running as a console app, it will always throw the error regardless of what thread the observation is executed on.

However, when I run this code as a test in NUnit as follows, it exits silently after 2 seconds (thread sleep time) without any error or message (expecting "completed"). So is it actually NUnit causing the issue?

[TestFixture]
class Program
{
    [Test]
    public void Test()
    {
        Enumerable.Range(0, 1)
                .ToObservable(Scheduler.Default)
                .Subscribe(
                    o => { throw new Exception("blah"); }, 
                    () => Console.WriteLine("completed"));
        Thread.Sleep(2000);
    }
}

解决方案

Rx does not catch exceptions thrown by observers. This is a very important design principle that has been discussed in length before, though for some reason it's only included as a footnote of §6.4 in the Rx Design Guidelines.

Note: do not protect calls to Subscribe, Dispose, OnNext, OnError and OnCompleted methods. These calls are on the edge of the monad. Calling the OnError method from these places will lead to unexpected behavior.

Essentially, this guideline ensures that, from the perspective of an observer, OnError will only be called by exceptions originating from the observable itself, including any calls to user code that participate directly in the computation (rather than merely observing the results). If this were not the case, then an observer may not be able to distinguish whether an exception passed to OnError is a bug in their OnNext handler or perhaps a bug in the observable.

But more importantly, it also ensures that any exception thrown by an OnNext handler goes unhandled. This makes it easier to debug your program and protects user data.

That being said, the reason why you may be observing different behavior when OnNext is executed on a pooled thread is simply a consequence of your debugging experience. Try enabling first-chance exceptions.

Furthermore, I'd also avoid the race condition by changing Thread.Sleep to Console.ReadKey().

这篇关于无扩展燕子从OnNext()呼吁一个线程池线程异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆