2016-11-12 2 views
0

マルチスレッドを使用して200ファイルを取得したいので、以下のようにTCLの例を変更します。 しかし、結果は奇妙です。出力ファイルの総数は約135です。スレッドの開始方法が変数$threadの値を変更するのは混乱していました。TCLでループを使ってマルチ・シアドを始めるには?

package require Thread 
puts "*** I'm thread [thread::id]" 

for {set thread 1} {$thread <= 200} {incr thread} { 
    set thread_ida $thread 
    tsv::set app global_thread_num $thread_ida 

    set id [thread::create -joinable { 

     puts [ tsv::get app global_thread_num ] 
     set thread_id [ tsv::get app global_thread_num ] 
     puts "${thread_id}thread_id" 
     set outFile "./test/${thread_id}" 
     append outFile ".tmd" 
     puts $outFile 
     set FileOut [open $outFile w+] 
     puts $FileOut "${thread_id}thread_id" 
    }] ;# thread::create 
    puts "*** Started thread $id" 
    lappend threadIds $id 
} ;# for 
puts "*** Existing threads: [thread::names]" 
# Wait until all other threads are finished 
foreach id $threadIds { 
    thread::join $id 
} 
puts "*** That's all, folks!" 

答えて

1

あなたが持っている問題は、次の2行ということです:

puts [ tsv::get app global_thread_num ] 
set thread_id [ tsv::get app global_thread_num ] 

が全く同じ値を取得することを保証、また彼らが全く設定と同期する可能性が高いされていません外部ループ内の共有変数の値。 Tclのスレッドには、起動時に相当量のオーバーヘッドがあります。

代わりに、プロシージャ内の作業の説明を含むスレッドを作成し、実際の処理を開始するためにIDを持つ単純なメッセージを送信する必要があります。作業をはるかに簡単に行うことができます。ここで重要な事は、我々は、メッセージを受信thread::waitとのメッセージを待機するためのスレッドを取得し、その後、thread::send -asyncでメッセージを送信することにより、作業を起動する各スレッド(DoWork)の手順を作成することです

package require Thread 
puts "*** I'm thread [thread::id]" 

for {set thread 1} {$thread <= 200} {incr thread} { 
    set id [thread::create -joinable { 
     proc DoWork {thread_id} { 
      # Only one puts here 
      puts "${thread_id}thread_id" 
      set outFile "./test/${thread_id}" 
      append outFile ".tmd" 
      puts $outFile 
      set FileOut [open $outFile w+] 
      puts $FileOut "${thread_id}thread_id" 
      # Close the channel, please... 
      close $FileOut 
      # Thread done, and since we're using joinable threads it should die now 
      thread::release 
     } 
     thread::wait 
    }] ;# thread::create 
    puts "*** Started thread $id" 
    lappend threadIds $id 
    # Start the work going, passing over the numeric ID in the "message" 
    thread::send -async $id [list DoWork $thread] 
} ;# for 
puts "*** Existing threads: [thread::names]" 
# Wait until all other threads are finished 
foreach id $threadIds { 
    thread::join $id 
} 
puts "*** That's all, folks!" 

。作品はthread::releaseでスレッドを破壊します。それを明示的に行う必要があります。それ以外の場合は、thread::waitに戻り、次のメッセージを待つことになります。


特定の配備で利用可能なハードウェアへの拡張が容易なため、実際には実動コードでスレッドプールを使用します。 のないDoWorkプロシージャは、プールの-initcmdオプションで定義されます。 thread::send -asyncはプールへのポスティング作業に置き換えられ、スレッドの代わりにジョブを待つことになります。

package require Thread 
puts "*** I'm thread [thread::id]" 

set pool [tpool::create -maxworkers 48 -initcmd { 
    proc DoWork {thread_id} { 
     # Only one puts here 
     puts "${thread_id}thread_id" 
     set outFile "./test/${thread_id}" 
     append outFile ".tmd" 
     puts $outFile 
     set FileOut [open $outFile w+] 
     puts $FileOut "${thread_id}thread_id" 
     # Close the channel, please... 
     close $FileOut 
    }  
}] 

for {set thread 1} {$thread <= 200} {incr thread} { 
    lappend work [tpool::post -nowait $pool [list DoWork $thread]] 
} 
# Wait until all work is finished 
foreach id $work { 
    tpool::wait $pool $id 
} 
puts "*** That's all, folks!" 
tpool::release $pool 
+0

私が使用している作業負荷がより複雑であると仮定しています。単一のスレッドで200個のファイルのそれぞれに1行だけを書き込むほうが簡単です。 –

+0

私のtclファイルをあなたのものとして修正しています。本当にありがとうございました〜そして、ついに間違いを見つけました〜私はスレッドを使用して、200本のファイルのそれぞれに1行だけ書くのではなく、 –

関連する問題