对于我的一篇论文的数据收集模块,我实现了一个简单的轮询机制。这是必需的,因为我将每个数据收集请求(许多之一)作为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()
...
}
上面代码的问题是它似乎无法正常工作 :在发出数据请求时,代码应打印“等待结果。 ..“然后,定期检查结果文件以进行修改(重新生成),打印进度点直到结果准备好,打印确认时。但是,实际行为是代码等待很长时间(我故意让一个请求长时间运行),没有打印任何东西,但显然检索结果和打印“等待结果......”和“准备好”同时。
在我看来,这是某种同步问题,但我无法弄清楚到底是什么。或者,也许它是别的东西而且我在某种程度上错过了它。 非常感谢您的建议和帮助!
答案 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 ...爆炸