2016-09-15 2 views
0

ブラックボックスジェネレータが完全にブロックされ、永遠に実行されるとします。私たちはTwistedを実行していますので、ブロックするものを処理する標準的な方法はdefersまたはdefers + threadsです。永続的に実行されるねじれたスレッドのフルブロックジェネレータ

# some very naive example 
from twisted.internet import reactor 

def aSillyBlockingMethod(): 
    for results in fullblocking_blockbox_generator_that_runs_forever(): 
     print results 

reactor.callInThread(aSillyBlockingMethod) 
reactor.run() 

yay!仕事は終わった! ...しかし正確ではない。

Twistedアプリ全体を停止したい限り、すべてが素晴らしいです。シャットダウンの手順の1つは〜threadpool.join()と呼ばれ、すべてのスレッドが終了するのを待っています。しかし、私たちのfullbocking ethernalではなく、blackboxジェネレータ。私たちは決して起こり得ない発電機からの結果を得る必要があるため、多くのことをループで行うことはできません。

インターネット全体をアイディアのためにブラウズしました。何もない。たぶん私は何か重要なものを見逃しているか、これを扱う巧妙な方法がありますか?

答えて

0

私はthis postから回答を得て、サンプルコードを追加しました。また、常にスレッドの開始点と終了点を明確に定義することをお勧めします。ご覧のように、スレッドが無制限に永久に実行されると、かなりスティッキーな状況が発生する可能性があります。そのように言われると、状況によっては避けられないこともあります(ただし、可能な限り回避しようとするべきではありません)。

ブラックボックスがTwistedから何も必要ない場合は、Twistedのコントロールの外側のデーモンスレッドとして起動することができます。これは、アプリケーションが停止したときに停止します。一般に、これは非常に危険なです。これは、スレッドをすぐに削除して、状態を破損状態にする可能性があるためです。いずれにせよ、ここでの例です:

from threading import Thread, Event 
from time import sleep 
from twisted.internet import reactor 

class BlackBox(Thread): 

    def __init__(self, stop_event=None): 
     super(BlackBox, self).__init__() 
     if not stop_event: 
      stop_event = Event() 
     self.stop_event = stop_event 

    def run(self): 
     while True: 
      print('running in thread') 
      if self.stop_event.is_set(): 
       print('STOPPING!') 
       break 
      sleep(1) 

t = BlackBox() 
t.daemon = True 
t.start() 
# reactor.callLater(5, t.stop_event.set)  # if you want to stop thread after 5 seconds 
reactor.run() 

より良いオプションは、このようなEventをチェックして、あなたのスレッドコード内の制御フローを持ち、アプリがシャットダウンしたときにトリガを開始します。このようなトリガーをTwistedでキャプチャするには、reactor.addSystemEventTriggerを使用します。

from threading import Event 
from time import sleep 
from twisted.internet import reactor 

def aSillyBlockingMethod(event): 
    while True: 
     print('running in thread') 
     if event.is_set(): 
      print('STOPPING') 
      break 
     sleep(1) 

stop_event = Event() 
reactor.callInThread(aSillyBlockingMethod, stop_event) 
reactor.addSystemEventTrigger('before', 'shutdown', stop_event.set) 
reactor.run() 

オプション#2は、スレッドコードを任意に停止しないので、あなたがツイストスレッドを管理させることができ、デーモン・スレッドよりもはるかに優れたソリューションであり、かつ適切な時期に停止することができますスレッドが(開発者とみなさ)。私はこれが助けてくれることを願っています

+0

広範な応答をありがとう。 'events'を使うことは、スレッドを外部から停止させる唯一の方法です。残念ながら、私が質問を書いているように、 'for'ループは' fullblocking_blockbox_generator_that_runs_forever'で 'next()'を呼び出し、そのコードジェネレータはそのジェネレータの深さにジャンプするので、ループで多くを行うことはできません。私たちの手は結ばれています。私たちのコードは歩留まりを待つことを余儀なくされ、その歩留まりは数秒で、あるいは1年でさえあります。それがこの質問の目標です。どのようにそのような状況に対処するのですか? – proxy

+1

私は、コードのスレッド部分へのアクセスが制限されていることを考慮に入れました。なぜなら、デーモンスレッドオプションを最初に提供した理由です。もう一つのビットは、誰かがこの記事につまずいている人を読んでいる人のためのものです;) –

関連する問題