实现简单轮询结果文件

时间:2014-05-07 12:40:09

标签: r debugging synchronization polling control-flow

对于我的一篇论文的数据收集模块,我实现了一个简单的轮询机制。这是必需的,因为我将每个数据收集请求(许多之一)作为SQL查询,通过Web表单提交,由 RCurl 代码模拟。服务器处理每个请求并生成一个文本文件,其中包含特定URL的结果(下面的代码中为RESULTS_URL)。无论请求如何,URL和文件名都是相同的(我不能改变它)。由于不同数据请求的处理时间显然不同,有些请求可能需要很长时间,因此我的R代码需要“知道”,当结果准备就绪(文件被重新生成)时,它可以检索它们。以下是我解决这个问题的方法。

POLL_TIME <- 5 # polling timeout in seconds

在函数srdaRequestData()中,在发出数据请求之前:

# check and save 'last modified' date and time of the results file
# before submitting data request, to compare with the same after one
# for simple polling of results file in srdaGetData() function
beforeDate <- url.exists(RESULTS_URL, .header=TRUE)["Last-Modified"]
beforeDate <<- strptime(beforeDate, "%a, %d %b %Y %X", tz="GMT")

<making data request is here>

srdaGetData()

之后调用的函数srdaRequestData()
# simple polling of the results file
repeat {
  if (DEBUG) message("Waiting for results ...", appendLF = FALSE)
  afterDate <- url.exists(RESULTS_URL, .header=TRUE)["Last-Modified"]
  afterDate <-  strptime(afterDate, "%a, %d %b %Y %X", tz="GMT")
  delta <- difftime(afterDate, beforeDate, units = "secs")
  if (as.numeric(delta) != 0) { # file modified, results are ready
    if (DEBUG) message(" Ready!")
    break
  }
  else { # no results yet, wait the timeout and check again
    if (DEBUG) message(".", appendLF = FALSE)
    Sys.sleep(POLL_TIME)
  }
}

<retrieving request's results is here>

模块的主要流程/事件序列是线性的,如下所示:

Read/update configuration file
Authenticate with the system
Loop through data requests, specified in configuration file (via lapply()),
  where for each request perform the following:
  {
    ...
    Make request: srdaRequestData()
    ...
    Retrieve results: srdaGetData()
    ...
  }

上面代码的问题是它似乎无法正常工作 :在发出数据请求时,代码应打印“等待结果。 ..“然后,定期检查结果文件以进行修改(重新生成),打印进度点直到结果准备好,打印确认时。但是,实际行为是代码等待很长时间(我故意让一个请求长时间运行),没有打印任何东西,但显然检索结果和打印“等待结果......”和“准备好”同时

在我看来,这是某种同步问题,但我无法弄清楚到底是什么。或者,也许它是别的东西而且我在某种程度上错过了它。 非常感谢您的建议和帮助!

1 个答案:

答案 0 :(得分:1)

在对问题的评论中,我相信MrFlick解决了问题:轮询逻辑似乎正常运行,但问题是进度消息不同步使用系统上的当前事件

默认情况下, R控制台输出缓冲。这是设计:加快速度,避免可能与频繁消息等相关的分散注意力的闪烁。我们倾向于忘记这一事实,特别是在我们以非常互动的方式使用R,运行各种广告之后控制台上的临时语句(控制台缓冲区在返回>提示符之前自动刷新)。

然而,有可能获得message()以及更实际的控制台输出&#34;实时&#34;通过在每个关键输出语句之后显式刷新控制台,使用flush.console()函数,或者在R GUI级别禁用缓冲(在控制台上右键单击,请参阅Buffered output Ctrl W项。也可以在Misc菜单中找到

这是一个明确使用flush.console的玩具示例。请注意使用cat()而不是message(),因为前者不会自动将CR / LF添加到输出中。然而,后者是有用的,因为它的消息可以用suppressMessages()等来抑制。同样如评论中所示,您可以捕捉&#34; \ b&#34; (退格)字符使数字相互覆盖。

CountDown <- function() {
  for (i in 9:1){
    cat(i)
    # alternatively to cat(i) use:  message(i)
    flush.console()    # <<<<<<<  immediate ouput to console.
    Sys.sleep(1)
    cat(" ")   # also try cat("\b") instead ;-)
  }
  cat("... Blast-off\n")
}

输出结果如下,在这个打印输出中当然不明显的是,在最终&#34; Blast off&#34;之前,每秒打印一个数字需要花费10秒钟。请删除flush.console()语句,输出将在10秒后立即生效,即函数终止时(除非控制台未在GUI级别缓冲)。

  

倒计时()    9 8 7 6 5 4 3 2 1 ...爆炸