當while循環留下您應該設置線程沒有在從worker
內誘發的回調,:
編輯:現在還支持後臺程序立即重啓
import time
import threading
class CoolThing(object):
def __init__(self):
self.thread = None
def run_in_background(self, callback, period=0.5):
wait_count = 0
while True:
if self.thread:
if self.thread[1].running or wait_count>10:
raise RuntimeError()
time.sleep(0.5)
wait_count += 1
else:
break
def worker():
t0 = time.time()
worker.running = True
while worker.running:
if time.time()-t0>2:
callback()
t0 = time.time()
time.sleep(period)
worker.callback()
worker.callback = self.dispose
self.thread = (threading.Thread(target=worker), worker)
self.thread[0].start()
def stop_background(self, join=False):
if not self.thread:
raise RuntimeError
self.thread[1].running = False
if join:
self.thread[0].join()
self.stopping = True
def dispose(self):
self.thread = None
self.stopping
def my_callback():
print "Beep"
if __name__=="__main__":
cool_thing = CoolThing()
cool_thing.run_in_background(my_callback, 0.5)
time.sleep(10)
cool_thing.stop_background()
# Immediatley restart process
cool_thing.run_in_background(my_callback, 0.5)
time.sleep(10)
cool_thing.stop_background()
print cool_thing.thread
time.sleep(3)
print cool_thing.thread
給出了輸出:
Beep
Beep
Beep
(<Thread(Thread-2, started 10760)>, <function worker at 0x02DEDD70>)
None
因此,在調用stop_background之後,self.thread仍然被設置,但後來它是None
。您也可以保存worker.callback變量並通過它的名稱調用dispose(),但這樣,代碼更加靈活。
編輯2:新要求,新的代碼示例
我做了一個單獨的類工人(SRP)和CoolThing舉辦這樣的員工名單中。如果啓動了run_background(...)
,它將檢查是否有任何工作者仍在運行(不停止請求),然後引發RuntimeError。否則,開始一個新的工作。 stop_background()
告訴每個工人停下來,每個工人調用一個回調,然後將這個工人從所有工人的清單中刪除。
import time
import threading
class Worker(threading.Thread):
def __init__(self, callback, period=0.5, finished_callback = None):
threading.Thread.__init__(self)
self.callback = callback
self.period = period
self._stop_requested = False
self._finished_callback = finished_callback
def run(self):
t0 = time.time()
while not self._stop_requested:
if time.time()-t0>2:
self.callback()
t0 = time.time()
time.sleep(self.period)
if self._finished_callback:
self._finished_callback(self)
def request_stop(self):
self._stop_requested = True
@property
def stopping(self):
return self._stop_requested
class CoolThing(object):
def __init__(self):
self.workers = []
self.workers_lock = threading.Lock()
def run_in_background(self, callback, period=0.5):
if len([w for w in self.workers if not w.stopping])>0:
raise RuntimeError()
worker = Worker(callback, period, finished_callback=self.dispose)
with self.workers_lock:
self.workers.append(worker)
worker.start()
def stop_background(self, join=False):
if len(self.workers) == 0:
raise RuntimeError()
for worker in self.workers:
worker.request_stop()
if join:
for worker in self.workers:
worker.join()
def dispose(self, worker):
with self.workers_lock:
self.workers.remove(worker)
def my_callback():
print "Beep"
if __name__=="__main__":
cool_thing = CoolThing()
cool_thing.run_in_background(my_callback, 0.5)
time.sleep(10)
print cool_thing.workers
cool_thing.stop_background()
# Immediatley restart process
cool_thing.run_in_background(my_callback, 0.5)
print cool_thing.workers
time.sleep(5)
print cool_thing.workers
time.sleep(5)
cool_thing.stop_background()
print cool_thing.workers
time.sleep(3)
print cool_thing.workers
我的第一反應是'self.thread [0]。加入() ',但這似乎並沒有殺死線程,它只是等待線程完成執行...... – mgilson
@mgilson:對。我不希望'stop_background()'在沒有明確請求的情況下被阻塞(見編輯)。 –