2

我正在开发一个使用 EXEC 命令运行生成文件的程序。这可能需要很长时间,所以我想把它放在后台,这样 GUI 就不会锁定。但是,我还希望禁用 GUI,并且仅在编译 make 文件时才运行进度条。

那么如何检测 TCL 中的后台进度何时完成呢?

编辑:它变得更加复杂,因为我的老板希望命令窗口保持打开(或可见),以便用户可以看到制作进度并查看它是否出错。

PS 搞清楚线程会更容易吗?我需要一些方法来防止 GUI 锁定(防止不响应)。

编辑:GUI 是用 TK 制作的。我认为 TK 是导致问题的单线程。或者可能是它默认为单线程,我想将其设置为多线程。

4

2 回答 2

2

正如@glenn-jackman 指出的那样,首选使用 fileevent (因为它应该在任何地方都可以使用)。

proc handle_bgexec {callback chan} {
    append ::bgexec_data($chan) [read $chan]
    if {[eof $chan]} {
        # end of file, call the callback
        {*}$callback $::bgexec_data($chan)
        unset ::bgexec_data($chan)
    }
}

proc bgexec {callback args} {
    set chan [open "| $args" r]
    fconfigure $chan -blocking false
    fileevent $chan readable [list handle_bgexec $callback $chan]
    return
}

调用它作为bgexec job_done cmd /c start /wait cmd /c make all-all. job_done完成后使用命令的输出调用。

也可以为这些事情使用线程,但这需要一个线程化的 tcl 构建(现在这是所有平台 AFAIK 的默认设置,但旧版本的 Tcl 尤其是 unix 下默认不构建一个线程化的 Tcl。)和Thread包(默认包含)。将它与线程一起使用的方法是:

thread::create "[list exec cmd /c start /wait cmd /c make all-all];[list thread::send [thread::id] {callback code}];thread::exit"

如果您需要定期调用它,可能值得只使用一个工作线程而不是为每个作业创建一个新线程。

编辑:添加/wait作为启动参数以保持第一个 cmd 运行。

cmd /c start /wait cmd /c make all-all
于 2012-08-24T20:46:15.260 回答
0

您想在管道中运行 make 过程并使用事件循环和 fileevent 来监视其进度(请参阅http://wiki.tcl.tk/880

proc handle_make_output {chan} {
    # The channel is readable; try to read it.
    set status [catch { gets $chan line } result]
    if { $status != 0 } {
        # Error on the channel
        puts "error reading $chan: $result"
        set ::DONE 2
    } elseif { $result >= 0 } {
        # Successfully read the channel
        puts "got: $line"
    } elseif { [chan eof $chan] } {
        # End of file on the channel
        puts "end of file"
        set ::DONE 1
    } elseif { [chan blocked $chan] } {
        # Read blocked.  Just return
    } else {
        # Something else
        puts "can't happen"
        set ::DONE 3
    }
}

set chan [open "|make" r]
chan configure $chan -blocking false
chan event $chan readable [list handle_make_output $chan]
vwait ::DONE
close $chan

我不确定vwait在 Tk 的事件循环中的使用。也许专家会在这里帮助我。

于 2012-08-24T17:45:09.470 回答