fix: EventCar 同车 Tick 串行并覆盖基类 Stop
上一拍未结束则跳过本拍,避免断网重试堆积;Stop 调用 base.Stop 并清空工作线程。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -8,6 +8,7 @@ using SimpleCore.PropType;
|
||||
using StandardScene;
|
||||
using StandardScene.Scheduler.FassEvent;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -68,6 +69,9 @@ namespace StandardScene.Scheduler
|
||||
/// <summary>记录每辆车上一周期的 CurrentNode,用于 PrevNode 触发与地标变化时清除任务防重复标记。</summary>
|
||||
[JsonIgnore] private readonly Dictionary<int, string> _prevNodeByCarId = new Dictionary<int, string>();
|
||||
|
||||
/// <summary>每车最多一个在飞 Tick,避免断网重试把 Task.Run 堆爆、同一车并发下发。</summary>
|
||||
[JsonIgnore] private readonly ConcurrentDictionary<int, byte> _tickInFlight = new ConcurrentDictionary<int, byte>();
|
||||
|
||||
/// <summary>进程运行状态扩展字段。</summary>
|
||||
public class EventCarMissionStatus : MissionStatus
|
||||
{
|
||||
@@ -140,9 +144,9 @@ namespace StandardScene.Scheduler
|
||||
Diagnosis.Post($"FASS EventCar 配置已加载:{path},事件数={_eventCars.Count}", "FassEventCar", true);
|
||||
}
|
||||
|
||||
/// <summary>停止轮询并等待工作线程结束(最多 2 秒)。</summary>
|
||||
/// <summary>停止轮询并等待工作线程结束(最多 2 秒)。覆盖基类 Stop,避免全量重载后线程仍在对全场车下发。</summary>
|
||||
[MethodMember(Name = "停止进程", Description = "停止 FASS 车辆事件轮询")]
|
||||
public void Stop()
|
||||
public override void Stop()
|
||||
{
|
||||
_started = false;
|
||||
try
|
||||
@@ -153,8 +157,10 @@ namespace StandardScene.Scheduler
|
||||
{
|
||||
}
|
||||
|
||||
status.status = "已停止";
|
||||
_workerThread = null;
|
||||
Diagnosis.Post("FASS车辆事件进程已停止", "FassEventCar", true);
|
||||
base.Stop();
|
||||
status.status = "已停止";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -182,14 +188,18 @@ namespace StandardScene.Scheduler
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 遍历所有 Car,构建快照并异步调用 Handler(与 FASS Task.Run 行为一致)。
|
||||
/// <para>
|
||||
/// 跳过 status 为空或 usage.refreshing=false 的车辆(未参与调度刷新的车不处理)。
|
||||
/// 当地标变化时清除 <see cref="FassEventCarHandler.ActiveTaskTag"/>,允许在新地标重新触发事件。
|
||||
/// </para>
|
||||
/// 遍历所有 Car,构建快照后 Task.Run 处理:一车断网不堵其它车。
|
||||
/// 同一车上一拍未结束则跳过本拍,禁止无界堆积。
|
||||
/// </summary>
|
||||
private void ProcessAllCars()
|
||||
{
|
||||
var handler = _handler;
|
||||
var eventCars = _eventCars;
|
||||
if (handler == null || eventCars == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var car in SimpleLib.GetAllCars().OfType<Car>())
|
||||
{
|
||||
if (car.status == null)
|
||||
@@ -207,13 +217,37 @@ namespace StandardScene.Scheduler
|
||||
_prevNodeByCarId.TryGetValue(car.id, out var prevNode);
|
||||
var snapshot = FassEventCarSnapshotFactory.Create(car, prevNode, FassEventCarSnapshotFactory.GetNextNodeCode(car));
|
||||
|
||||
Task.Run(() => _handler.HandleCarTimerTick(car, snapshot, _eventCars));
|
||||
|
||||
if (!string.Equals(prevNode, currentNode, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_prevNodeByCarId[car.id] = currentNode;
|
||||
ClearTaskTags(car);
|
||||
}
|
||||
|
||||
if (!_tickInFlight.TryAdd(car.id, 0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var carId = car.id;
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_started)
|
||||
handler.HandleCarTimerTick(car, snapshot, eventCars);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Diagnosis.Post(
|
||||
$"FASS车辆事件处理异常 car={carId}:{ExceptionFormatter.FormatEx(ex)}",
|
||||
"FassEventCar",
|
||||
true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_tickInFlight.TryRemove(carId, out _);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace StandardScene.Scheduler.FassEvent
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 单次 TimerTick 对一辆车的处理入口(通常在 Task.Run 中调用)。
|
||||
/// 单次 TimerTick 对一辆车的处理入口(由 EventCarMission 按车 Task.Run,同车同时只跑一拍)。
|
||||
/// 仅处理 TriggerEvent=TimerTick 的配置项。
|
||||
/// </summary>
|
||||
public void HandleCarTimerTick(Car car, FassEventCarSnapshot snapshot, IReadOnlyList<FassEventCarConfig> eventCars)
|
||||
|
||||
Reference in New Issue
Block a user