2016-11-18 1 views
1

GUIをTcl/Tkに組み込んでいます。このGUIには、ディレクトリを作成するボタンがあります。 ディレクトリが非常に大きいので、待機中にGUIをロックしたくない場合があります。openとvwaitを使った別のプロセスのTarファイル

これを実現するには、コマンドパイプとvwaitにopenを使用していますが、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をロックアップするのですか?パイプが役立つ開封後

fconfigure $pipe -blocking false 

を追加

+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

関連する問題