実行中のスレッドに対し外から操作をする

  • 40
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

概要

無限ループのスレッドを作成したのはいいものの,threadingのドキュメントを見ると

現状では、優先度 (priority)やスレッドグループがなく、スレッドの破壊 (destroy)、中断 (stop)、一時停止 (suspend)、復帰 (resume)、割り込み (interrupt) は行えません

とか書いてあって,どうやって止めたらいいのか・・・とハマったのでメモしておきます.

例えば,Raspberry PiかなんかでLチカさせるのに,複数のLEDを独立してLチカさせてスピードも変えたい,とかいったときに載せたコードがそのまま使えそうです.

私はマルチスレッド初心者で間違ってること書いてるかもしれないので,
教えてください!

Event オブジェクトを使う

Eventオブジェクトのドキュメントには次のように書いてあります.

イベントは、あるスレッドがイベントを発信し、他のスレッドはそれを待つという、スレッド間で通信を行うための最も単純なメカニズムの一つです。

というわけで,メインスレッドから止まれ,というイベントを設定してあげます.

実装例

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time, threading

class Hoge():

    def __init__(self):
        self.stop_event = threading.Event() #停止させるかのフラグ
        self.inc_event = threading.Event()  #刻み幅を増やすかのフラグ

        #スレッドの作成と開始
        self.thread = threading.Thread(target = self.target)
        self.thread.start()

    def target(self):
        """ひたすら 'count 数字' と出力する"""
        count = 1
        step = 1
        while not self.stop_event.is_set():
            time.sleep(1)
            print "count %d" % count

            if self.inc_event.is_set():
                step += 1
                self.inc_event.clear()
            count += step

    def stop(self):
        """スレッドを停止させる"""
        self.stop_event.set()
        self.thread.join()    #スレッドが停止するのを待つ

    def inc(self):
        """targetで出力する数字の刻み幅を増やすフラグを立てる"""
        self.inc_event.set()

if __name__ == '__main__':
    h = Hoge()      #スレッドの開始
    time.sleep(3)   
    h.inc()         #countの刻み幅を2に
    time.sleep(3)
    h.stop()        #スレッドの停止
    time.sleep(3)   #メインスレッドが終わる前に止まってる!
    print "finish"

結果

count 1
count 2
count 3
count 5
count 7
count 9
finish

setDaemonとかしてないのに,メインスレッドの終了を待たずに終わってくれています.

また,__exit()__を実装して,中にstop()とか書いとけば,with Hoge()とかして中の処理が終わったら勝手に停止してくれます.