我有一个要求,在最初的10秒钟延迟后,我需要每10分钟执行一次SomeMethod,但要注意的是,在SomeMethod完成后应启动10分钟计时器。这是简单的示例:

Start Task 00:00:00
(10 second delay)
SomeMethod executed at 00:00:10 (takes 15 minutes)
(10 minute delay)
SomeMethod executed at 00:25:10
... and so on.


我知道如何使用TPL做到这一点。我可以使用Task.Delay启动任务并执行SomeMethod,然后在每次完成操作(ContinueWith TaskStatus.RanToCompletion)之后,创建一个新任务并再次执行SomeMethod

我的问题是使用Observable.Timer可以吗?就像是...

Observable.Timer(TimeSpan.FromSeconds(10), TimeSpan.FromMinutes(10))


这段代码的问题在于,如果SomeMethod需要15分钟,我将有两个不同的SomeMethod实例在运行,这是我不希望的。我希望10分钟计时器在SomeMethod完成后启动。是否可以使用Observable还是应该留在TPL?

编辑:忘记提及我要SomeMethod在其自己的线程中运行。

最佳答案

您应该对使用Observable.Timer做更多调查。它的工作原理几乎就像您想直接使用一样。

关于Rx的一件重要事情是,它可以确保您永远不会获得单个订阅的并发执行。尽管Rx可能启用各种多线程方案,但它始终会序列化订阅。

因此,以该可观察的订阅为例:

Observable
    .Timer(TimeSpan.FromSeconds(10.0), TimeSpan.FromSeconds(2.0))
    .Timestamp()
    .Subscribe(x =>
    {
        Thread.Sleep(5000);
        Console.WriteLine(x.ToString());
    });


我创建了一个可观察对象,它将等待10秒才能开始发出值,然后尝试每2秒发出一次值。

然后,我添加了.Timestamp()来准确记录何时生成值。

最后,我已经订阅了一个强制5秒钟线程睡眠的观察者。

这是前四个值的输出:

0@2015-08-31 10:44:34 +00:00
1@2015-08-31 10:44:39 +00:00
2@2015-08-31 10:44:44 +00:00
3@2015-08-31 10:44:49 +00:00


您会注意到,两个值之间的差距为5秒。这非常接近您想要的。 Rx看到两秒已过去,并立即执行下一个值。

但是还有另一个Rx运算符可以完全满足您的要求-.Generate(...)。这是生成各种可观察流的非常强大的运算符。

您想要这样使用它:

Observable
    .Generate(0, x => true, x => x + 1, x => x,
        x => x == 0 ? TimeSpan.FromSeconds(10.0) : TimeSpan.FromSeconds(2.0))
    .Timestamp()
    .Subscribe(x =>
    {
        Thread.Sleep(5000);
        Console.WriteLine(x.ToString());
    });


在这种情况下,它完全可以按照您想要的方式工作。这是前十个值:

0@2015-08-31 10:48:27 +00:00
1@2015-08-31 10:48:34 +00:00
2@2015-08-31 10:48:41 +00:00
3@2015-08-31 10:48:48 +00:00
4@2015-08-31 10:48:55 +00:00
5@2015-08-31 10:49:02 +00:00
6@2015-08-31 10:49:09 +00:00
7@2015-08-31 10:49:16 +00:00
8@2015-08-31 10:49:23 +00:00
9@2015-08-31 10:49:30 +00:00


它每7秒触发一次。生成运算符的2和观察者的5。

您显然可以投入所需的时间。

关于c# - 具有Task.Delay的Observable.Timer或TPL,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32307852/

10-09 06:43