1

別のスレッドで実行されている長時間実行プロセスの実行を終了しようとすると、問題が発生します。

以下はプログラムです。WorkOneはサブプロセスを作成し、ログ行を生成する長時間実行プロセス「adblogcat」を実行します。main()でWorkOneを起動し、5秒間待ってから、停止しようとします。複数の実行により、複数の出力が得られます

import threading
import time
import subprocess
import sys

class WorkOne(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.event = threading.Event()  
        self.process = subprocess.Popen(['adb','logcat'], stdout=subprocess.PIPE, stderr=sys.stdout.fileno())      

    def run(self):   
        for line in iter(self.process.stdout.readline,''):            
            #print line
            if self.event.is_set():
                self.process.terminate()
                self.process.kill()
                break;
        print 'exited For'

    def stop(self):
        self.event.set()

def main():

    print 'starting worker1'
    worker1 = WorkOne()
    worker1.start()
    print 'number of threads: ' + str(threading.active_count())
    time.sleep(5)
    worker1.stop()
    worker1.join(5)
    print 'number of threads: ' + str(threading.active_count())

if __name__ == '__main__':
    main()

時々私は[A]を取得します:

starting worker1
number of threads: 2
number of threads: 2
exited For

時々私は[B]を得る:

starting worker1
number of threads: 2
number of threads: 1
exited For

時々私は[C]を得る:

starting worker1
number of threads: 2
number of threads: 2

私はいつも[B]を取得することを期待すべきだと思います。ここで何が問題になっていますか?

4

2 に答える 2

0

変化する

       if self.event.is_set():
            self.process.terminate()
            self.process.kill()
            break;

        if self.event.is_set():
            self.process.terminate()
            self.process.wait()
            break

セミコロンは、ここに問題があることを示しています。

wait()スレッドがないと、ブロックwork1.join(5)がすぐに解除されることがあると思います。そのような場合、threading.active_count()2 を返します。

そして、@ A.Rodasが言うように、結合が完了するまでブロックが解除されないようにするwork1.join(5)必要があります。work1.join()work1


ところで、なぜ連続して電話terminateをかけたいのかわかりません。killUnix では、kill はより深刻な終了の形式です。Windows では、それらは同一です。したがって、kill を呼び出す場合は、terminate を呼び出す必要はありません。

によって呼び出されるプログラムを知っているのでsubprocess、terminate でそれを停止するのに十分かどうかも知っておく必要があります。

したがって、必要なのは か のいずれか 1 つだけself.process.terminate()ですself.process.kill()

于 2013-03-18T02:11:18.800 に答える
0

[B] は、サブプロセスに 10 秒もかからない場合にのみ可能だと思います。メイン スレッドは 5 秒間スリープし、その後worker5 秒のタイムアウト内に終了しますjoin()

タイムアウト引数があるため、10 秒以上は呼び出しworker後も生きている可能性があります。join()次に、[A] (サブプロセスが数秒後に終了) または [C] (サブプロセスがかなり遅れて終了) を取得できます。

常に [B] を取得するには、タイムアウト引数を削除しjoin()て、メイン スレッドがworker終了するまで待機するようにします (または、kill 呼び出しをループの外に配置して、10 秒以内にプロセスを強制終了するようにします)。

于 2013-03-18T02:34:26.533 に答える