You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Anylogic仿真:如何移除流程图中所有Agent?代码报错求助

处理AnyLogic中批量移除流程块内Agent的报错问题

我需要在必要时移除流程图所有块中的剩余Agent,但AnyLogic没有自带的相关方法。自己写了遍历所有块逐个移除Agent的函数,但因为涉及Service、Queue、ConveyorPath、Batch、Wait等多种块类型,方案不仅无效还频繁报错。

原实现代码

for (ConveyorPath conveyor : ersterTeilConveyor) {
    List list = conveyor.getAgents();
    for (Object a : list) {
        Kerze k = (Kerze) a;
        traceln(k.currentBlock().getName() + " " + k.getIndex());
        conveyor.removeAgent(k);
        enter4.take(k);
    }
}
for (Agent block : ersterTeilBlock) {
    if (block instanceof Queue) {
        Queue queue = (Queue) block;
        int size = queue.size();
        for (int i = 0; i < size; i++) {
            queue.removeFirst();
        }
    } else if (block instanceof Batch) {
        Batch batch = (Batch) block;
        for (Agent k : batch.contents()) {
            traceln(k.currentBlock().getName() + " " + k.getIndex());
            batch.remove(k);
            enter4.take(k);
        }
    } else if (block instanceof Delay) {
        Delay delay = (Delay) block;
        if (delay.size() > 0) {
            Kerze k = (Kerze) delay.get(0);
            traceln(k.currentBlock().getName() + " " + k.getIndex());
            delay.remove(k);
            enter4.take(k);
        }
    }
}   
for (ConveyorPath conveyor : zweiterTeilConveyor) {
    List list = conveyor.getAgents();
    for (Object a : list) {
        Kerze k = (Kerze) a;
        traceln(k.currentBlock().getName() + " " + k.getIndex());
        conveyor.removeAgent(k);
        enter4.take(k);
    }
}
for (Agent block : zweiterTeilBlock) {
    if (block instanceof Queue) {
        Queue queue = (Queue) block;
        for (Agent k : queue.contents()) {
            traceln(k.currentBlock().getName() + " " + k.getIndex());
            queue.remove(k);
            enter4.take(k);
        }
    } else if (block instanceof Batch) {
        Batch batch = (Batch) block;
        for (Agent k : batch.contents()) {
            traceln(k.currentBlock().getName() + " " + k.getIndex());
            batch.remove(k);
            enter4.take(k);
        }
    } else if (block instanceof Service) {
        Service service = (Service) block;
        int size = service.queueSize();
        if (size > 0) {
            for (int i = 0; i < size; i++) {
                Kerze k = (Kerze) service.queueGet(i);
                traceln(k.currentBlock().getName() + " " + k.getIndex());
                service.queueRemove(k);
                enter4.take(k);
            }
        }
        if (service.delaySize() > 0) {
            Kerze k2 = (Kerze) service.delayGet(0);
            traceln(k2.currentBlock().getName() + " " + k2.getIndex());
            service.delayRemove(k2);
            enter4.take(k2);
        }
    } else if (block instanceof Wait) {
        Wait wait = (Wait) block;
        for (Agent k : wait.contents()) {
            traceln(k.currentBlock().getName() + " " + k.getIndex());
            wait.remove(k);
            enter4.take(k);
        }
    }
}

报错信息

Exception during discrete event execution:

root.enter4.output.output:

Internal error: agent 34291 is already pending as 'ready' on some other port: root.enter4.output.output.out

java.lang.RuntimeException: root.enter4.output.output:

Internal error: agent 34291 is already pending as 'ready' on some other port: root.enter4.output.output.out

    at com.anylogic.engine.Engine.error(Unknown Source)
    at com.anylogic.engine.Agent.error(Unknown Source)
    at com.anylogic.engine.Utilities.error(Unknown Source)
    at com.anylogic.engine.Utilities.error(Unknown Source)
    at com.anylogic.libraries.processmodeling.ExtEntityImpl.c(Unknown Source)
    at com.anylogic.libraries.processmodeling.OutputBlock.notifyReady(Unknown Source)
    at com.anylogic.libraries.processmodeling.OutputBuffer.a(Unknown Source)
    at com.anylogic.libraries.processmodeling.OutputBuffer.take(Unknown Source)
    at com.anylogic.libraries.processmodeling.Enter.take(Unknown Source)
    at prozess.Main.removeKerzen2(Main.java:7449)
    at prozess.Main._sink2_onEnter_xjal(Main.java:6164)
    at prozess.Main$14.onEnter(Main.java:1895)
    at prozess.Main$14.onEnter(Main.java:1)
    at com.anylogic.libraries.processmodeling.Sink.b(Unknown Source)
    at com.anylogic.libraries.processmodeling.Sink$1.onEnter(Unknown Source)
    at com.anylogic.libraries.processmodeling.InputBlock$1.b(Unknown Source)
    at com.anylogic.libraries.processmodeling.InPort.a(Unknown Source)
    at com.anylogic.libraries.processmodeling.InPort.receiveImmediately(Unknown Source)
    at com.anylogic.libraries.processmodeling.InputBlock$1.a(Unknown Source)
    at com.anylogic.libraries.processmodeling.OutPort.a(Unknown Source)
    at com.anylogic.libraries.processmodeling.OutPort.b(Unknown Source)
    at com.anylogic.libraries.processmodeling.PlainTransfer$1.a(Unknown Source)
    at com.anylogic.libraries.processmodeling.OutPort.a(Unknown Source)
    at com.anylogic.libraries.processmodeling.OutPort.b(Unknown Source)
    at com.anylogic.libraries.processmodeling.OutPort.a(Unknown Source)
    at com.anylogic.libraries.processmodeling.OutputBlock.a(Unknown Source)
    at com.anylogic.libraries.processmodeling.OutputBlock$2.a(Unknown Source)
    at com.anylogic.libraries.processmodeling.OutputBlock$2.action(Unknown Source)
    at com.anylogic.libraries.processmodeling.AsynchronousExecutor_xjal$a.execute(Unknown Source)
    at com.anylogic.engine.LibraryEventHandler$i.execute(Unknown Source)
    at com.anylogic.engine.Engine.f(Unknown Source)
    at com.anylogic.engine.Engine.fn(Unknown Source)
    at com.anylogic.engine.Engine$i.run(Unknown Source)

问题分析

报错核心原因是同一个Agent被重复调用enter4.take(k),触发场景包括:

  • 部分Agent被误判存在于多个块集合中(比如ConveyorPath和其他块的集合重复包含了同一Agent所在的块)
  • Batch、Wait块使用contents()遍历的方式有误:遍历原集合时直接修改集合(移除Agent)会导致遍历异常,且部分块的contents()返回的是视图而非实际可修改集合
  • 移除Agent后调用take()时,Agent可能还处于原有块的端口调度队列中,导致端口冲突报错

修正方案

核心优化思路

  1. 用全局Agent集合去重,确保每个Agent只被处理一次
  2. 针对不同块类型使用正确的移除API,避免遍历修改原集合的问题
  3. 移除Agent时先清理原有块的关联,再处理后续的take()操作

修正后的代码

// 先收集所有需要移除的Kerze,用HashSet自动去重
Set<Kerze> kerzenToRemove = new HashSet<>();

// 收集ConveyorPath中的Agent
for (ConveyorPath conveyor : ersterTeilConveyor) {
    for (Object a : conveyor.getAgents()) {
        kerzenToRemove.add((Kerze) a);
    }
}
for (ConveyorPath conveyor : zweiterTeilConveyor) {
    for (Object a : conveyor.getAgents()) {
        kerzenToRemove.add((Kerze) a);
    }
}

// 收集各类块中的Agent
for (Agent block : ersterTeilBlock) {
    if (block instanceof Queue) {
        Queue queue = (Queue) block;
        for (Agent k : queue.contents()) {
            kerzenToRemove.add((Kerze) k);
        }
    } else if (block instanceof Batch) {
        Batch batch = (Batch) block;
        for (Agent k : batch.contents()) {
            kerzenToRemove.add((Kerze) k);
        }
    } else if (block instanceof Delay) {
        Delay delay = (Delay) block;
        for (int i = 0; i < delay.size(); i++) {
            kerzenToRemove.add((Kerze) delay.get(i));
        }
    }
}

for (Agent block : zweiterTeilBlock) {
    if (block instanceof Queue) {
        Queue queue = (Queue) block;
        for (Agent k : queue.contents()) {
            kerzenToRemove.add((Kerze) k);
        }
    } else if (block instanceof Batch) {
        Batch batch = (Batch) block;
        for (Agent k : batch.contents()) {
            kerzenToRemove.add((Kerze) k);
        }
    } else if (block instanceof Service) {
        Service service = (Service) block;
        // 收集队列中的Agent
        for (int i = 0; i < service.queueSize(); i++) {
            kerzenToRemove.add((Kerze) service.queueGet(i));
        }
        // 收集正在服务的Agent
        for (int i = 0; i < service.delaySize(); i++) {
            kerzenToRemove.add((Kerze) service.delayGet(i));
        }
    } else if (block instanceof Wait) {
        Wait wait = (Wait) block;
        for (Agent k : wait.contents()) {
            kerzenToRemove.add((Kerze) k);
        }
    }
}

// 逐个处理去重后的Agent
for (Kerze k : kerzenToRemove) {
    traceln(k.currentBlock().getName() + " " + k.getIndex());
    // 先从当前所在块精准移除
    ProcessBlock currentBlock = (ProcessBlock) k.currentBlock();
    if (currentBlock instanceof ConveyorPath) {
        ((ConveyorPath) currentBlock).removeAgent(k);
    } else if (currentBlock instanceof Queue) {
        ((Queue) currentBlock).remove(k);
    } else if (currentBlock instanceof Batch) {
        ((Batch) currentBlock).remove(k);
    } else if (currentBlock instanceof Delay) {
        ((Delay) currentBlock).remove(k);
    } else if (currentBlock instanceof Service) {
        Service service = (Service) currentBlock;
        if (service.queueContains(k)) {
            service.queueRemove(k);
        }
        if (service.delayContains(k)) {
            service.delayRemove(k);
        }
    } else if (currentBlock instanceof Wait) {
        ((Wait) currentBlock).remove(k);
    }
    // 最后执行take操作,避免端口冲突
    enter4.take(k);
}

关键说明

  • 使用HashSet收集Agent自动去重,彻底避免重复处理同一个Agent
  • 先收集所有目标Agent再统一处理,避免遍历块集合时修改集合导致的异常
  • 通过k.currentBlock()获取Agent实际所在的块,精准调用对应移除API,避免误操作
  • 移除Agent时先清理其与原块的关联,再执行take(),解决端口冲突问题

内容的提问来源于stack exchange,提问作者Ephemere

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 17:03:14