Как выполнять функцию каждую секунду

Я хочу запустить функцию, для выполнения которой требуется менее одной секунды. Я хочу запускать его в цикле каждую секунду. Я не хочу ждать одну секунду между запуском функции, как Sys.sleep.

while(TRUE){
  # my function that takes less than a second to run
  Sys.sleep(runif(1, min=0, max=.8))  

  # wait for the remaining time until the next execution...
  # something here
}

Я мог записать a starttime <- Sys.time() и выполнить сравнение каждой итерации через цикл, что-то вроде этого...

starttime <- Sys.time()
while(TRUE){
  if(abs(as.numeric(Sys.time() - starttime) %% 1) < .001){
    # my function that takes less than a second to run
    Sys.sleep(runif(1, min=0, max=.8))  
    print(paste("it ran", Sys.time()))
  }
}

Но моя функция никогда не выполняется.

Я знаю, что у python есть пакет для такого рода вещей. У R тоже есть тот, о котором я не знаю? Спасибо.

Ответ 1

Вы можете отслеживать время с помощью system.time

while(TRUE)
{
    s = system.time(Sys.sleep(runif(1, min = 0, max = 0.8)))
    Sys.sleep(1 - s[3]) #basically sleep for whatever is left of the second
}

Вы также можете использовать proc.time напрямую (какие вызовы system.time), которые по некоторым причинам получили лучшие результаты для меня:

> system.time(
  for(i in 1:10)
  {
    p1 = proc.time()
    Sys.sleep(runif(1, min = 0, max = 0.8))
    p2 = proc.time() - p1
    Sys.sleep(1 - p2[3]) #basically sleep for whatever is left of the second
  })
   user  system elapsed 
   0.00    0.00   10.02

Ответ 2

Вот несколько альтернатив. Эти не блокируют. То есть вы все еще можете использовать консоль для запуска другого кода во время их работы.

1) Попробуйте tcltk after в пакете tcltk:

library(tcltk)

run <- function () { 
  .id <<- tcl("after", 1000, run) # after 1000 ms execute run() again
  cat(as.character(.id), "\n")    # replace with your code
}

run()

Запуск этого на свежем сеансе R дает:

after#0 
after#1 
after#2 
after#3 
after#4 
after#5 
after#6 
after#7 
...etc...

Чтобы остановить это tcl("after", "cancel",.id).

2) tcltk2 Другая возможность - это tclTaskSchedule в пакете tcltk2:

library(tcltk2)

test <- function() cat("Hello\n")  # replace with your function
tclTaskSchedule(1000, test(), id = "test", redo = TRUE)

Остановите это с помощью:

tclTaskDelete("test")

или redo= может указать, сколько раз он должен работать.

Ответ 3

Пакет shiny имеет функцию invalidateLater(), которая может использоваться для запуска функций. Посмотрите http://shiny.rstudio.com/gallery/timer.html

Ответ 4

Хотя уже очень поздно.

В качестве альтернативы мы можем использовать рекурсию. Я не знаю, если это решение, которое вы ищете. Но он выполняет функцию через регулярные промежутки времени.

ssc <-  function(){
x <- rnorm(30,20,2)
print(hist(x))
 Sys.sleep(4)

 ssc()

 }
ssc()

Ответ 5

Еще одна неблокирующая альтернатива, о которой стоит упомянуть, предоставляется библиотекой (позже) с использованием рекурсива later():

print_time = function(interval = 10) {
  timestamp()
  later::later(print_time, interval)
}

print_time()

Пример взят здесь.