2016-11-02 32 views
0

Pythonでスレッドを強制終了する問題について、高度に解決された解決策を理解しようとしています:Is there any way to kill a Thread in Python?。著者はクラスStoppableThreadを提供し、それをどのように使用するか(すなわち、stop()メソッドを呼び出し、join()を使用してスレッドが正常に終了するのを待って)説明します。PythonのスレッディングのStoppableThreadサブクラスの使用例

私は簡単な例を使って、この仕事をするために試してみた:

import time 
import threading 

class StoppableThread(threading.Thread): 
    """Thread class with a stop() method. The thread itself has to check 
    regularly for the stopped() condition.""" 

    def __init__(self, *args, **kwargs): 
     super(StoppableThread, self).__init__(*args, **kwargs) 
     self._stop = threading.Event() 

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

    def stopped(self): 
     return self._stop.isSet() 

def run_forever(): 
    while True: 
     print("Hello, world!") 
     time.sleep(1) 

thread = StoppableThread(target=run_forever) 

thread.start() 
time.sleep(5) 
thread.stop() 
thread.join() 

は私がthreadが停止される前に、プログラムがHello, world!の約5倍を印刷することを期待します。しかし、私が見ていることは、それが無期限に印刷を続けることだけです。

誰かがStoppableThreadサブクラスの正しい使い方を明確にすることはできますか?

答えて

1

問題は赤色でコメントされています。 whileループがチェックされていない場合、stopped()状態が発生します。これを使用して、今すぐ終了すべきスレッドに「メッセージ」を送ることができますが、それは自動的には行いません。

whileループにif句を追加し、停止した条件を検出すると終了する必要があります。

だから、これを行うと、それが動作するはずです:

import time 
import threading 

class StoppableThread(threading.Thread): 
    """Thread class with a stop() method. The thread itself has to check 
    regularly for the stopped() condition.""" 

    def __init__(self, *args, **kwargs): 
     super(StoppableThread, self).__init__(*args, **kwargs) 
     self._stop = threading.Event() 

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

    def stopped(self): 
     return self._stop.isSet() 

    def run(self): 
     while True: 
      if self.stopped(): 
       return 
      print("Hello, world!") 
      time.sleep(1) 

thread = StoppableThread() 

thread.start() 
time.sleep(5) 
thread.stop() 
thread.join() 

か、StoppableThreadをサブクラス化することができます

import time 
import threading 

class StoppableThread(threading.Thread): 
    """Thread class with a stop() method. The thread itself has to check 
    regularly for the stopped() condition.""" 

    def __init__(self, *args, **kwargs): 
     super(StoppableThread, self).__init__(*args, **kwargs) 
     self._stop = threading.Event() 

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

    def stopped(self): 
     return self._stop.isSet() 


class pup(StoppableThread): 
    def __init__(self, *args, **kwargs): 
     super(pup, self).__init__(*args, **kwargs) 

    def run(self): 
     while True: 
      if self.stopped(): 
       return 
      print("Hello, world!") 
      time.sleep(1) 

thread = pup() 

thread.start() 
time.sleep(5) 
thread.stop() 

thread.join() 

あなたのスレッドが作業を行い、その後、眠るものだ、とうんざりするまでループする場合は、これは非常に良い方法ではなく、睡眠中の状態を検出しないためです。スレッドで長時間スリープしている場合は、スレッドを終了する前に期限切れにする必要があります。

これらのケースでは、代わりにキューを使用しています。スレッドを起動する前に、私はキューを作成し、これをパラメータとしてスレッドに渡します。 sleep(30)をQueue.get(True、30)に置き換えます。これは30秒間スリープするか、メッセージがあるまでスリープします。私はこのメッセージに基づいて行動することができます。スレッドをもっと深く伝える必要がある場合は、シャットダウンしたり、他のことをすることができます。

ハヌ

+0

おそらくコード全体を含めることはできますか? 'run_forever'を' StoppableThread'のクラスメソッド( 'self'を使うために必要です)にすると' thread = StoppableThread(target = run_forever) 'をしようとすると' NameError'が出ます。 –

+0

私は完全なコードを追加しました。私はちょうどあなたがあなたのrunメソッドの名前を変更してスレッドの外に置いたことに気付きました。上記(おそらく)は動作します。また、ターゲットキーワードパラメータは必要ありません。 – Hannu

+0

アプリケーションにいくつかの停止可能なスレッドを配置する予定の場合、StoppableThreadをサブクラス化する別のコードスニペットを追加しました。 – Hannu

関連する問題