2016-11-18 38 views
1

我有一个内置在Tcl/Tk中的GUI,它有一个可以打开目录的按钮。 该目录可能非常大,所以我不想在等待时锁定GUI。使用打开和vwait在单独的进程中打开文件

为了达到这个目的,我使用了open命令管道和vwait,但是当tar运行时,GUI仍然没有响应。这是我的代码:

set ::compress_result 0 
set pipe [open "|$tar_executable -cf $folder_to_tar.tar $folder_to_tar" r+] 
fileevent $pipe readable "set ::compress_result [gets $pipe line]" 

vwait ::compress_result 
set return_value $::compress_result 
unset ::compress_result 
close $pipe 

为什么这仍然阻挡Tcl的事件循环,并锁定了GUI?

+1

在我潜入之前,有没有使用'r +'模式的理由?我期望'r'(这实际上是可省略的,因为它是默认值)。 –

+0

这就是我从tcl wiki复制而来的。哈哈。 – TheBat

回答

2

你有问题的关键是这一行:

fileevent $pipe readable "set ::compress_result [gets $pipe line]" 

读取来自管的管线立即因为[gets …]是在双引号的字符串。更改为:

fileevent $pipe readable {set ::compress_result [gets $pipe line]} 

使事情工作,因为它推迟从管道的读数,直到管道变得可读。但是,要这样做,它依赖于pipe变量是全局变量。它实际上是更好地做到这一点:

fileevent $pipe readable [list apply {pipe { 
    global compress_result 
    set compress_result [gets $pipe line] 
}} $pipe] 

这是相当丑陋,笨拙的调试,所以我们反而实际上使用一个辅助程序:

proc pipedone {pipe} { 
    global compress_result 
    set compress_result [gets $pipe line] 
} 
fileevent $pipe readable [list pipedone $pipe] 

这里使用的list做“引用这作为以后的可运行脚本“,以应对您在变量中可能遇到的任何意想不到的技巧。它知道如何正确引用事情,所以你不必这样做。


在Tcl 8.6中,你最好使用协程。

coroutine piperead apply {{tar folder} { 
    # Open the pipe 
    set pipe [open |[list $tar -cf $folder.tar $folder] "r"] 
    # Wait until readable 
    fileevent $pipe readable [info coroutine] 
    yield 
    # Read and close 
    set return_result [gets $pipe line] 
    close $pipe 
    return $return_result 
}} $tar_executable $folder_to_tar 
+0

谢谢!我通过转义[gets ...] - > \\ [gets ... \\]来修复它 – TheBat

0

添加

fconfigure $pipe -blocking false 
开放管道将帮助后

相关问题