AnyLogic仿真停止报错及Wait.free()失效问题求助
Wait.free() Failures & Engine Event Issues in AnyLogic Scheduling Model Let's break down what's happening here and how to fix these frustrating intermittent issues:
Root Cause Analysis
The core problem here is that you're using custom Java Threads to interact with AnyLogic's Process Modeling Library blocks (like Wait). AnyLogic's simulation engine runs on a single-threaded event loop—when you bypass this with external threads, you create race conditions and state inconsistencies:
- Threads can modify the
Waitblock's internal state while the engine is already processing events for it, leading to missedfree()calls or corrupted event queues. - The negative timeout error happens because the engine's internal event scheduler gets an invalid (negative) time value from a corrupted
Waitblock state. - Unfinished events left in the queue when stopping the simulation are a direct result of these unsynchronized thread operations.
Step-by-Step Fixes
1. Ditch Custom Threads—Use AnyLogic's Native Event System
AnyLogic has built-in tools to handle your scheduling logic without manual threads. Here's how to refactor your Scheduling Agent:
- Replace the
Thread.start()logic with a Statechart (ideal for cyclic logic like your "wait → free → wait for finish" flow):- Create a Statechart with three states:
WaitingForJob,ReleasingJob,WaitingForCompletion. - In
WaitingForJob: Use aWait for Signalaction, where the signal is triggered when a job enters the correspondingWaitblock (use theWaitblock'sonEnterevent to send this signal). - In
ReleasingJob: CallWaitblock.free(a_Job)directly in the state's entry action (this runs in the engine's main thread, so no synchronization issues). - In
WaitingForCompletion: Wait for a signal triggered by theServiceblock'sonExitevent (when the job finishes processing). - Add transitions to loop back to
WaitingForJobafter completion.
- Create a Statechart with three states:
2. If You Must Use Threads (Not Recommended), Synchronize with the Engine
If you can't fully refactor away threads, wrap all calls to AnyLogic blocks in engine.invokeLater() to force them to run in the engine's main event loop:
new Thread(new Runnable() { public void run() { synchronized (sync_obj) { sync_obj.waituntilJobarrives(); // Wrap the Wait.free() call to run in the engine thread engine.invokeLater(() -> { sync_obj.Waitblock.free(a_Job); }); sync_obj.waituntilJobisfinished(); repeat(); } } });
This ensures that modifying the Wait block's state doesn't conflict with the engine's own event processing.
3. Fix the Negative Timeout Error
This error is a symptom of the thread-safety issue. Once you move all Wait block operations to the engine's main thread (either via Statecharts or invokeLater), the internal event scheduler won't receive invalid negative time values anymore. Double-check that you aren't dynamically setting timeouts on the Wait block that could accidentally result in negative values.
4. Eliminate Stopping-Time Event Residues
The "engine still has events scheduled" error happens because unsynchronized threads leave invalid events in the engine's queue. By aligning all operations with the engine's event loop, the simulation will properly clean up all events when stopped—no more residual events.
Bonus: Simplify Synchronization with AnyLogic Tools
Instead of using manual sync_obj.wait()/notify() calls, leverage AnyLogic's built-in synchronization features:
- Use Signals to trigger state transitions between agents.
- Use Shared Resources if you need to coordinate access to machines across agents.
- For job tracking, use the
Waitblock'sentitiescollection to check for waiting jobs (e.g.,Waitblock.entities.size() > 0) instead of custom wait logic.
内容的提问来源于stack exchange,提问作者Hans Zhou

