如何安排在给定条件成立后结束的定期工作?

时间:2015-01-23 09:44:01

标签: scala akka

我查看了akka schedulerexample here,它允许我安排定期和单个任务。我需要使用以下签名创建一个方法:

def doWhile(fn: => Unit, whileFn: => Boolean, period:Long) = {
  // while whileFn evaluates to true, repeat fn every period millisecs
}

我可以将fn包含在评估fnNew的另一个方法whileFn中,如果为true则执行fn。然后我可以安排fnNew定期执行。但这似乎是一个糟糕的黑客。在fnNew评估为假的那一刻,我希望whileFn“未计划”。什么是正确的方法?

编辑:我想避免使用显式actor,并希望避免使用共享状态,如下面的代码所示:

def doRegularly(fn: => Unit, periodMillis:Long) = 
    scheduler.schedule(0 seconds, periodMillis milliseconds)(fn)
def doWhile(fn: => Unit, whileFn: => Boolean, period:Long) = {
  var c:Option[Cancellable] = None
  c = Some(doRegularly(
            if (whileFn) fn 
            else {
               if (c.isDefined)  c.get.cancel
            }, period))
}

(具有共享值c

2 个答案:

答案 0 :(得分:2)

我认为你可以利用scheduleOnce来完成你想要的,而不是在doWhile的定义中拥有共享状态。如果你这样定义doWhile

def doWhile(fn: => Unit, whileFn: => Boolean, duration:FiniteDuration)(implicit sys:ActorSystem) {
  if (whileFn){
    fn
    sys.scheduler.scheduleOnce(duration)(doWhile(fn, whileFn, duration))(sys.dispatcher)
  }
} 

然后,您可以使用以下代码调用它:

implicit val system = ActorSystem("SchedTest")        
var count = 1
doWhile(printAndInc, count <= 10, 1 second)

def printAndInc{
  println(s"count is $count")
  count += 1
}

如果你运行上面的代码,你会看到它打印数字1到10,并在第二次暂停之间。

答案 1 :(得分:1)

docs,您可以使用cancel


//This will schedule to send the Tick-message
//to the tickActor after 0ms repeating every 50ms
val cancellable =
  system.scheduler.schedule(0 milliseconds,
    50 milliseconds,
    tickActor,
    Tick)

//This cancels further Ticks to be sent cancellable.cancel()

schedule方法返回类型为Cancellable的对象,该对象具有cancel方法。 我不确定,您打算如何使用whileFn,但只要它返回false,就在Cancellable对象上调用cancel方法。