1

简单的新手在这里。我刚开始用 simpy 进行 Speaker-Moderator 模拟。这是我的代码

import simpy

def speaker(env):
    try:
        print("Speaker start to talk at: {}".format(env.now))
        speak_time = 40
        print ("Speaker want to speak for {}".format(speak_time))
        yield env.timeout(speak_time)
        print ("Speaker finish the talk at: {}".format(env.now))
   except simpy.Interrupt as interrupt:
        print (interrupt.cause)

def moderator(env):
    for i in range(3):
        print("Moderator let the speaker number {} to begin the speak".format(i))
        speaker_proc = env.process(speaker(env))

        print("Time now: {}".format(env.now))
        time_limit = env.timeout(30)
        results = yield speaker_proc | time_limit
        print("Moderator check whether speaker passed the time limit or no")
        print("Time limit passed: {}".format (speaker_proc not in results))


        if speaker_proc not in results:
            print("Time now: {}".format(env.now))
            speaker_proc.interrupt()
            print ("Moderator stop the talk at: {}".format(env.now))
        print()
        print()

env = simpy.Environment()
env.process(moderator(env))
env.run()    

当我以 speak_time > 30 或 speak_time < 30 运行它时,它没有问题,但如果我将函数扬声器中的 speak_time 更改为 30,则会出现如下错误:

RuntimeError: <Process(speaker) object at 0x9e17930> has terminated and cannot be interrupted.

发生了什么?

4

1 回答 1

1

你在这里遇到了一个奇怪的角落案例。虽然您观察到的行为完全是有意的,但对于 SimBy 新手来说并不容易理解。

print()在您的moderator()流程中添加了两个以显示发生了什么:

import simpy


def speaker(env):
    try:
        print("Speaker start to talk at: {}".format(env.now))
        speak_time = 30
        print("Speaker want to speak for {}".format(speak_time))
        yield env.timeout(speak_time)
        print("Speaker finish the talk at: {}".format(env.now))
    except simpy.Interrupt as interrupt:
        print(interrupt.cause)


def moderator(env):
    for i in range(3):
        print("Moderator let the speaker number {} to begin the speak".format(i))
        speaker_proc = env.process(speaker(env))

        print("Time now: {}".format(env.now))
        time_limit = env.timeout(30)
        print('Timeout created')
        results = yield speaker_proc | time_limit
        print("Moderator check whether speaker passed the time limit or no")
        print("Time limit passed: {}".format(speaker_proc not in results))

        if speaker_proc not in results:
            print("Time now: {}".format(env.now))
            print(speaker_proc.is_alive)
            speaker_proc.interrupt()
            print("Moderator stop the talk at: {}".format(env.now))
        print()
        print()

env = simpy.Environment()
env.process(moderator(env))
env.run()

输出:

Moderator let the speaker number 0 to begin the speak
Time now: 0
Timeout created
Speaker start to talk at: 0
Speaker want to speak for 30
Speaker finish the talk at: 30
Moderator check whether speaker passed the time limit or no
Time limit passed: True
Time now: 30
False
Traceback (most recent call last):

那么发生了什么?

  1. 主持人在其第一个 之前一直处于活动状态yield。在此期间,它会创建扬声器进程和超时。

  2. 超时立即触发并添加到事件队列中。

  3. 主持人产生条件事件。

  4. 扬声器运行并创建超时。它也被立即触发和调度(与主持人超时同时,但在事件队列中插入它之后)。

  5. 处理版主超时时触发 Condition 事件。

  6. 当主持人恢复时,条件事件只保存主持人超时的结果,但发言者进程也终止。您可以通过speaker_proc.is_alive酒店查看此信息。

本指南包含有关此主题的一些更深入的信息。

于 2017-01-22T15:23:36.643 回答