我使用Python 3.4和3.6。我将sched.scheduler
用于典型的1小时间隔的未来事件。我在threading.Thread中运行调度程序,因此它是非阻塞的。
我运行第二个threading.Thread监视每个5秒的全局参数_busy
。在全局级别reset()
可以将此参数设置为False。
开启"重置",取消调度程序中的所有剩余事件。
最后,我在两个线程上使用.join()
作为清理。
但是,具有调度程序的线程在退出之前等待下一个(已取消)调度程序事件。这可能是在那个小时的间隔之后。
如何强制sched.scheduler
更新"在取消所有事件之后,它是否已经完成并且调度程序线程退出了?
import threading
import time
import sched
import winsound
def ScheduleSound(*args):
''' Beep as demo for slowscan '''
winsound.Beep(args[-1], 500)
class SlowScanSchedule(object):
'''
Main interface for slow scan schedule i.e.
- read and store content of ini-file
- add actions to schedule
- start schedule and schedule monitor thread
Example:
eggs = SlowScanSchedule("slowscan01.ini")
eggs.start()
eggs.schedule.queue
eggs._monitorthread.isAlive()
eggs._schedulethread.isAlive()
eggs.reset() # abort schedule ... takes some time
'''
def __init__(self, filename, **kwargs):
self.schedule = sched.scheduler(time.time, time.sleep)
# self.slowscan = omiconfig.IniFile(filename=filename)
# demo entries for starttime and schedule
self.timestart = time.mktime(time.localtime())
self.slowscan = [[10, 7, 1500], [10, 42, 1500], [10, 8, 1500], \
[300, 34, 1500], [300, 9, 1500], [300, 67, 1500]]
self._monitorthread = None
self._schedulethread = None
self._busy = False
# removed all logging for demo
self._update()
def _update(self):
'''fill scheduler'''
self.reset() # reset scheduled tasks
previousdelay = 0.0
for exposevalues in self.slowscan:
self._add(previousdelay, ScheduleSound, *exposevalues)
previousdelay += exposevalues[0]
def _add(self, secondsdelay, executeobject, *executeargs):
'''Auxiliary: add actions to schedule'''
self.schedule.enterabs(self.timestart + secondsdelay,
1,
executeobject,
argument=(executeargs))
def reset(self):
'''Stop thread with scheduler'''
self._busy = False
if self._monitorthread is not None:
self._monitorthread.join()
self._schedulethread.join()
self._monitorthread = None
self._schedulethread = None
def start(self):
'''Start schedule and monitor threads'''
if self._monitorthread is not None:
try:
self.reset()
except:
self._monitorthread = None
self._schedulethread = None
self._schedulethread = ScheduleThread(self.schedule)
self._monitorthread = MonitorThread(self)
class MonitorThread(threading.Thread):
'''Auxiliary object for scheduler monitor inside thread'''
def __init__(self, monitor):
'''Create and start thread for scheduler monitor'''
threading.Thread.__init__(self)
self._lock = threading.Lock()
self.monitor = monitor
self.monitor._busy = True
self.start()
def run(self):
'''Non-blocking thread that monitors global _busy and schedule'''
while self.monitor._busy and not self.monitor.schedule.empty():
time.sleep(5)
self._lock.acquire()
while not self.monitor.schedule.empty():
self.monitor.schedule.cancel(self.monitor.schedule.queue[-1])
self._lock.release()
self.monitor._busy = False
class ScheduleThread(threading.Thread):
'''Auxiliary object for scheduler inside thread'''
def __init__(self, schedule, **kwargs):
threading.Thread.__init__(self)
self.schedule = schedule
self.start()
def run(self):
self.schedule.run(blocking=True)