【问题标题】:How do I interrupt or cancel a SimPy Timeout event?如何中断或取消 SimPy 超时事件?
【发布时间】:2016-05-14 04:20:16
【问题描述】:

我想创建一个带有回调的计时器,可以使用 SimPy 中断或重置。如果中断,我不希望执行回调,如果重置,我希望计时器以与env.now 相同的延迟重新启动。最初只需使用env.timeout,这似乎是一件容易的事情。但是,文档说明:

要真正让时间在模拟中流逝,有超时事件。超时有两个参数:延迟和可选值:Timeout(delay, value=None)。它在创建过程中自行触发,并在现在 + 延迟时自行安排。因此,succeed() 和 fail() 方法无法再次调用,您必须在创建超时时将事件值传递给它。

因为模拟开始触发,我不能添加回调,因为你不能调用fail,所以我不能中断超时。

我考虑过只实现一个等待一个时间步长并检查标志是否被中断或到达它正在等待的env.now 的进程,但这似乎非常低效,如果我有很多计时器(我会的),我担心生成器的数量会压倒模拟。 (超时功能似乎通过在模拟的未来自行安排来工作,这就是为什么你可以让大量的人四处奔波)。

所以规范是 - 创建一个在指定时间后触发回调的事件,但可以在该时间发生之前重置或中断。有什么想法吗?

【问题讨论】:

    标签: python simulation simpy


    【解决方案1】:

    好吧,如果我正确理解了您的问题,您可以做的一件事是创建一个带有等待方法的 Timer 类,该方法检查 simpy.Interrupt。你可以实现stop(),这样当它被调用时,你也调用interrupt()。这样,只要之前调用了 interrupt(),就不会执行回调。重置方法将简单地再次调用stop()(中断)和start(),从而将操作设置回running()并再次调用wait(),允许在每次超时后再次执行回调,直到再次调用中断。

    以下是此类Timer 类的示例实现:

    import simpy
    
    class Timer(object):
    
        def __init__(self, env, delay, callback):
            self.env      = env 
            self.delay    = delay
            self.action   = None
            self.callback = callback
            self.running  = False
            self.canceled = False
    
        def wait(self):
            """
            Calls a callback after time has elapsed. 
            """
            try:
                yield self.env.timeout(self.delay)
                self.callback()
                self.running  = False
            except simpy.Interrupt as i:
                print "Interrupted!"
                self.canceled = True
                self.running  = False
    
        def start(self):
            """
            Starts the timer 
            """
            if not self.running:
                self.running = True
                self.action  = self.env.process(self.wait())
    
        def stop(self):
            """
            Stops the timer 
            """
            if self.running:
                self.action.interrupt()
                self.action = None
    
        def reset(self):
            """
            Interrupts the current timer and restarts. 
            """
            self.stop()
            self.start()
    

    【讨论】:

    • 很好的答案!我已经测试过并且start/stop 工作,只要你yieldtimer.action。但是,它看起来不像 reset 工作 - 环境只是出于某种原因没有收到消息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-12
    相关资源
    最近更新 更多