0

我有一个 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";
    }
}

问候

4

1 回答 1

1

Tcl 可以同时做几件事,特别是当它本身在等待时会受到 I/O 限制。要做到这一点,我们需要利用 eggdrop (我认识那种类型的bind)正在运行事件循环的事实,并使用fileevent命令。该fileevent命令很棒,因为它可以让我们安排一些代码在频道上“发生某事”时运行;当通道是管道(或套接字)时,当有一些文本要读取或通道关闭时,可以使用可读事件来做某事。(在您真正阅读某些内容之前,很难区分差异。)

让我们把这些位放在一起:管道和结果报告。我提出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 代替的“副本”作为练习;除了可能要解压缩的参数之外,这完全是一个剪切-粘贴的工作。)异步编程您习惯的要复杂一些,但是只要您对回调使用命名过程,您就可以工作而不会太困惑。

忽略机器,专注于更高层次上正在发生的事情。重写unrar解析其参数并要求unrar作为子进程异步运行。每当有输出时,它就会被触发unrar.report(一次一行)将其写入日志。您可能还想在其他地方报告它/以及。当管道完成时,unrar.done被调用以便它可以记录它已经完成。我将名称传递给unrar.reportunrar.done因为这样就可以看到完成的内容;了解正在发生的事情有时是异步程序的一个问题,因此准确地说是有帮助的。(这是一个明确的专业提示!)

您可以一次启动任意多次。做太多(多少取决于您的硬件),您的计算机会变慢,可能很多,但它最终会赶上。

于 2016-09-17T15:55:04.037 回答