запуск фонового процесса в R Shiny

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

Ниже мой скрипт. Процесс в этом скрипте засыпает на 10 секунд, после чего извлекается список имен файлов в текущей папке. Фоновый процесс находится в функции printLS(). Это выполняется в фоновом режиме функцией r_bg().

      library(shiny)
library(callr)

ui <- fluidPage(
  textOutput("clock"), br(), 
  actionButton("startjob","Start Job"), br(), br(), 
  uiOutput("LS")
)

server <- function(input, output, session) 
{
  output$clock <- renderText({
    invalidateLater(1)
    format(Sys.time(), "%d %b %H:%M:%S")
  })

  global <- reactiveValues(result = NULL)

  printLS <- function() {
    Sys.sleep(10)
    result <- system2(
      command = "ls",
      args    = c("-l"),
      stdout  = TRUE,
      stderr  = TRUE
    )
  }

  observeEvent(input$startjob, {
    global$result <- r_bg(func = printLS, supervise = F)
    global$result$wait()
  })

  output$LS <- renderUI({
    req(global$result)

    if (!global$result$is_alive())
      p(HTML(paste(global$result$get_result(), sep = "", collapse = "<br>")))
  })
}

shinyApp(ui = ui, server = server)

В приложении также отображаются часы. К сожалению, часы перестают работать, когда запущен фоновый процесс. Я хотел бы, чтобы часы продолжали работать во время фонового процесса. Я попробовал это, удалив «global$result$wait()». Но тогда кажется, что фоновый процесс работает вечно, не предоставляя никаких выходных данных (например, список файлов в текущей папке).

Теперь мой вопрос: как я могу заставить часы продолжать работать, пока фоновый процесс работает?

1 ответ

Как объяснено в примерах здесь , wait()означает, что мы должны дождаться результата фонового задания, прежде чем продолжить остальные процессы.

Один из способов поддерживать актуальность часов во время выполнения фонового задания — использовать проверку того, завершено ли задание (обратите внимание, что лучше использовать poll_io()чем is_alive(), как объясняется в этом комментарии Github ). Я сделал что-то подобное в этом вопросе , хотя общее приложение немного сложнее.

Вот что вам нужно изменить на сервере:

        observeEvent(input$startjob, {
    global$result <- r_bg(func = printLS, supervise = F)
  })
  
  output$LS <- renderUI({
    req(input$startjob)
    if (global$result$poll_io(0)["process"] == "timeout") {
      invalidateLater(1000)
    } else {
      p(HTML(paste(global$result$get_result(), sep = "", collapse = "<br>")))
    }
  })

Обратите внимание, что system2(command = "ls", args = c("-l"), stdout = TRUE, stderr = TRUE)не работал на моем ноутбуке, поэтому я использовал system("ls -l")вместо.

Другие вопросы по тегам