我有一个tcl脚本,但它一次只能解压缩一件事。我现在必须等待它完成的那一刻,然后我才能做下一个。我如何同时做两件事?
bind pubm - "*complete*" unrar
proc unrar {nick host handle channel text} {
set text [stripcodes bcru $text]
set name [lindex [split $text] 2];
set dir "/tmp/unrar"
if {[catch {exec /bin/sh -c "unrar e $dir/$name $dir/archive/$name"} error]} {
putlog "error: $error";
}
}问候
发布于 2016-09-17 23:55:04
Tcl可以一次做几件事,特别是当它本身在等待时会受到I/O限制的时候。为此,我们需要利用eggdrop (我认识这种类型的bind)正在运行事件循环这一事实,并使用fileevent命令。fileevent命令很棒,因为它可以让我们在通道上“发生一些事情”时安排一些代码运行;当通道是管道(或套接字)时,当有一些文本要读取或通道关闭时,可以使用readable事件来做一些事情。(在你真正读到一些东西之前,很难区分它们。)
让我们把这些部分放在一起:管道和返回结果报告。我将展示asyncpipe命令!
proc asyncpipe {command lineCallback closedCallback} {
set f [open |$command "r"]
fileevent $f readable [list asyncpipe.callback $f $lineCallback $closedCallback]
# There's no output from this command directly, and it returns nearly instantly if your pipeline is sensible.
}
proc asyncpipe.callback {channel lineCallback closedCallback} {
if {[gets $channel line] >= 0} {
uplevel "#0" $lineCallback [list $line]
} elseif {[eof $channel]} {
catch {close $channel}
uplevel "#0" $closedCallback
}
}好了,这是建立基本的机器,但它还不是特别清楚。下面是如何使用它。
bind pubm - "*complete*" unrar
proc unrar {nick host handle channel text} {
set text [stripcodes bcru $text]
set name [lindex [split $text] 2];
set dir "/tmp/unrar"
asyncpipe [list unrar e $dir/$name $dir/archive/$name] \
[list unrar.report putlog $name] [list unrar.done $name]
}
proc unrar.report {name line} {
putlog "unrar $name :>> $line"
}
proc unrar.done {name} {
putlog "all done with unrar $name"
}这将在发生时报告unrar的输出,并允许您一次运行两个。(编写一个使用unzip的“copy”作为练习;除了可能的unzip参数之外,这完全是一个“剪切粘贴”的工作。)异步编程比您习惯的要复杂一些,但是只要您对回调使用命名过程,您就可以工作而不会太困惑。
忽略机器,专注于更高层次上正在发生的事情。重写的unrar解析其参数,并要求unrar作为子进程异步运行。只要有输出,它就会被触发到unrar.report中(一次一行),它会将输出写入日志。您可能希望在其他地方报告它,而不是。当管道结束时,会调用unrar.done,这样它就可以记录它已经完成了。我将名称传递给unrar.report和unrar.done,因为这样就可以看到完成了什么;知道发生了什么在异步程序中偶尔会有问题,所以它有助于准确。(这是一个明确的建议!)
你可以一次启动任何你想要的东西。做太多(多少取决于你的硬件),你的计算机会变慢,可能会很慢,但它最终会赶上。
https://stackoverflow.com/questions/39547751
复制相似问题