后台线程调度操作时,Rx TestScheduler引发NullReference异常

尼尔·麦克马伦

根据一些评论,我应该清楚地表明,这个问题是关于TestScheduler为什么抛出空引用异常,而不是如何使测试通过。一个较早的示例假定与TPL的交互是问题的原因,但我现在发现触发此行为不是必需的,因此我用一个更简单的测试用例替换了代码

我在尝试将rx测试“虚拟时间” TestScheduler与后台线程结合在一起时遇到一些问题。在文章的底部显示了我发现的最简单的方法来演示该问题。

该代码只是在运行一个后台线程,该线程订阅带有超时的可观察序列。

超时是由TestScheduler驱动的,当我在主线程上进行超时时,将生成空引用异常:

断言失败。虚拟时间00:00:00.1394720,异常System.NullReferenceException:对象引用未设置为对象的实例。在System.Reactive.Concurrency.VirtualTimeScheduler 2.GetNext() at System.Reactive.Concurrency.VirtualTimeSchedulerBase2.AdvanceTo(TAbsolute time)处..... UnitTest1.cs:line

该故障似乎对所使用的IObservable的确切类型不敏感,但似乎取决于Timeout选择器的存在。但是有趣的是,测试通常会在虚拟时间失败,因为超时是在火灾引发的超时之前。

运行与控制台应用程序相同的代码也似乎可以正常工作,尽管该问题似乎很容易受到干扰(可能是竞争条件),因此这可能会引起麻烦。

进一步的研究和评论强烈暗示,该行为是由于在后台线程调度其超时操作而使调度程序前进时发生的竞争条件引起的

在此先感谢您提供的任何信息...

using Microsoft.Reactive.Testing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Reactive.Linq;
using System.Threading;

namespace UnitTestProject1
{
[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestBackgroundThreadWithTestScheduler()
    {
        var scheduler = new TestScheduler();
        var seq = Observable.Never<string>();

        bool subscribed = false;
        ThreadPool.QueueUserWorkItem(_ =>
        {
            Thread.Sleep(100); //wait a bit to give main thread chance to start advancing scheduler
            seq.Timeout(TimeSpan.FromSeconds(10), scheduler)
               .Subscribe(s => {/*never called*/});
            subscribed = true; //signal we're subscribed
        });

        //----  Uncommenting this line to avoid the race condition appears to fix the test ----
        //while (!subscribed) Thread.Yield(); 

        //Advance the scheduer in small increments to maximise our chances of hitting the race
        var watch = scheduler.StartStopwatch();
        try
        {
            while (watch.Elapsed < TimeSpan.FromSeconds(20)) scheduler.AdvanceBy(10);
        }
        //NullReference is thrown unexpectedly
        catch (NullReferenceException ex)
        {
            Assert.Fail("Virtual time {0}, exception {1}", watch.Elapsed, ex);
        }
        catch (TimeoutException)
        {
            //desired result is a TimeoutException so this is a test pass
        }
    }
}
}
布兰登

这条线在堆栈跟踪System.Reactive.Concurrency.VirtualTimeScheduler2.GetNext()是一个线索,那就是错误确实是您访问从2个线程调度器( 该TestScheduler不是线程安全的 但目前的一个错误TestScheduler从多个线程访问它时)。

您的第一个评论可能是正确的:后台任务正在添加到调度程序中,就像您的其他任务正在推进调度程序一样。

尝试在访问调度程序的语句周围添加锁,看看是否可以解决您的问题。

当然,真正的解决方法是在设置好自己的后台任务信号后,让测试任务在继续之前先等待该信号。因为即使TestScheduler没有错误,您的测试也有一个竞争条件,即测试线程可以在后台线程订阅可观察对象之前完成。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

后台线程调度操作时,Rx TestScheduler引发NullReference异常

来自分类Dev

在主线程中引发异常时停止后台线程

来自分类Dev

处理异常时引发异常

来自分类Dev

Qt:处理从后台线程的处理程序引发的异常

来自分类Dev

向ServiceStack添加会话cookie时出现nullreference异常

来自分类Dev

SAML注销时出现ADFS NullReference异常(事件303)

来自分类Dev

SAML注销时出现ADFS NullReference异常(事件303)

来自分类Dev

在python线程中引发异常

来自分类Dev

PayPal .NET SDK-新的Payment()-引发NullReference异常

来自分类Dev

如何运行不阻止主线程但在失败时在主线程中引发异常的异步IO操作?

来自分类Dev

如何运行不阻止主线程但在失败时在主线程中引发异常的异步IO操作?

来自分类Dev

从后台线程更新集合中的item属性时发生异常

来自分类Dev

数值溢出时引发异常

来自分类Dev

设置名称时引发异常

来自分类Dev

调用getFriends时引发异常

来自分类Dev

程序在引发异常时挂起

来自分类Dev

从主线程执行方法时如何引发异常

来自分类Dev

为什么仅在调试时才引发跨线程异常?

来自分类Dev

如何在后台线程上调度操作[可可]

来自分类Dev

Xamarin构建失败。在UI线程中调度方法调用时引发了异常

来自分类Dev

每次对它执行操作时,SqlDataReader对象都会引发异常

来自分类Dev

使用Retrofit 2和Rx在Scheduler.Worker线程上引发致命异常

来自分类Dev

从Python中的线程引发多个异常

来自分类Dev

在后台线程中全局捕获WCF异步调用引发的异常

来自分类Dev

静态类成员在构造时引发异常

来自分类Dev

解析JSON文件时isNothing引发异常

来自分类Dev

引发异常时如何设置退出代码

来自分类Dev

出现问题时如何引发异常?

来自分类Dev

测试引发异常的方法时验证行为

Related 相关文章

  1. 1

    后台线程调度操作时,Rx TestScheduler引发NullReference异常

  2. 2

    在主线程中引发异常时停止后台线程

  3. 3

    处理异常时引发异常

  4. 4

    Qt:处理从后台线程的处理程序引发的异常

  5. 5

    向ServiceStack添加会话cookie时出现nullreference异常

  6. 6

    SAML注销时出现ADFS NullReference异常(事件303)

  7. 7

    SAML注销时出现ADFS NullReference异常(事件303)

  8. 8

    在python线程中引发异常

  9. 9

    PayPal .NET SDK-新的Payment()-引发NullReference异常

  10. 10

    如何运行不阻止主线程但在失败时在主线程中引发异常的异步IO操作?

  11. 11

    如何运行不阻止主线程但在失败时在主线程中引发异常的异步IO操作?

  12. 12

    从后台线程更新集合中的item属性时发生异常

  13. 13

    数值溢出时引发异常

  14. 14

    设置名称时引发异常

  15. 15

    调用getFriends时引发异常

  16. 16

    程序在引发异常时挂起

  17. 17

    从主线程执行方法时如何引发异常

  18. 18

    为什么仅在调试时才引发跨线程异常?

  19. 19

    如何在后台线程上调度操作[可可]

  20. 20

    Xamarin构建失败。在UI线程中调度方法调用时引发了异常

  21. 21

    每次对它执行操作时,SqlDataReader对象都会引发异常

  22. 22

    使用Retrofit 2和Rx在Scheduler.Worker线程上引发致命异常

  23. 23

    从Python中的线程引发多个异常

  24. 24

    在后台线程中全局捕获WCF异步调用引发的异常

  25. 25

    静态类成员在构造时引发异常

  26. 26

    解析JSON文件时isNothing引发异常

  27. 27

    引发异常时如何设置退出代码

  28. 28

    出现问题时如何引发异常?

  29. 29

    测试引发异常的方法时验证行为

热门标签

归档