Rx并发计划与锁定

时间:2013-02-13 17:57:16

标签: c# unit-testing system.reactive

我再次与Rx挣扎。这次我遇到了Observable.Interval的问题。

我的要求是:

  • 我需要每1秒运行一次数据收集。
  • 我需要每隔5秒检查参数的变化。
  • 我在检查更改时无法收集数据。
  • 如果数据收集或检查更改的时间超过1秒,请不要将这些更改排队,只需跳过它们即可。
  • 如果在数据收集过程中发生更改检查时间,我希望它等待执行。

我已尝试使用Observables作为间隔,并且发现默认情况下Intervals将排队错过的刻度!最后,在创建了一个完整的控制台应用程序后,我找到了一个演示我需要的示例。此实现似乎只适用于Scheduler.NewThread。我的新问题是我无法测试此实现,因为测试调度程序似乎是CurrentThread。

我的控制台应用示例代码:

var otherThreadScheduler = Scheduler.NewThread; 
cancel = otherThreadScheduler.Schedule(
    TimeSpan.FromSeconds(1),
    recursive =>
        {
            lock (obj)
            {

                Console.WriteLine(
                    "Processing Data - Thread ID = " + Thread.CurrentThread.ManagedThreadId);

                var t = new Task(
                    () =>
                        {
                            Console.WriteLine(
                                "Hi I'm the task on thread {0}",
                                Thread.CurrentThread.ManagedThreadId);

                            Thread.Sleep(2000);
                        });

                t.Start();

                Console.WriteLine(
                    "Processing Data Waiting for it to finish - Thread ID = "
                    + Thread.CurrentThread.ManagedThreadId);

                t.Wait();
            }
            Console.WriteLine("Processing Data finished - Thread ID = " + Thread.CurrentThread.ManagedThreadId);

            recursive(TimeSpan.FromSeconds(1));
        });

cancel2 = otherThreadScheduler.Schedule(
    TimeSpan.FromSeconds(1),
    recursive =>
        {
            lock (obj)
            {
                Console.WriteLine("Processing Detection - Thread ID = " + Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(10000);
            }

            recursive(TimeSpan.FromSeconds(5));
        });

这是不可测试的原因是我的实际代码中的任务是可模拟的所以我嘲笑它循环,直到我发出信号停止但是因为我的代码执行task.Wait(),我当前的线程阻塞所以我永远不会发出信号要返回的任务。所有这一切都是为了模拟长时间运行的数据收集并验证更改检测不会触发。

所以我的问题是:对我的需求有更优雅的解决方案吗?

1 个答案:

答案 0 :(得分:0)

而不是使用Task.Wait并阻止当​​前线程,

将完成代码写为延续可能更好。 即,使用Task.ContinueWith(_ => recursive(...))