fix(pause): 修复暂停管理器销毁时的并发问题

- 在销毁过程中收集暂停组和处理器快照,避免并发修改异常
- 在锁外通知所有之前暂停的组恢复,保持生命周期信号一致性
- 添加异常处理确保单个处理器失败不影响其他处理器的通知
- 修改文件过滤规则以正确包含测试文件路径
This commit is contained in:
GeWuYou 2026-03-02 21:46:53 +08:00 committed by gewuyou
parent ccc3d046ca
commit 50c73a7d7c
2 changed files with 58 additions and 5 deletions

View File

@ -28,6 +28,9 @@ public class PauseStackManager : AbstractContextUtility, IPauseStackManager, IAs
if (_disposed)
return ValueTask.CompletedTask;
List<PauseGroup> pausedGroups;
IPauseHandler[] handlersSnapshot;
_lock.EnterWriteLock();
try
{
@ -36,6 +39,15 @@ public class PauseStackManager : AbstractContextUtility, IPauseStackManager, IAs
_disposed = true;
// 收集所有当前暂停的组
pausedGroups = _pauseStacks
.Where(kvp => kvp.Value.Count > 0)
.Select(kvp => kvp.Key)
.ToList();
// 获取处理器快照
handlersSnapshot = _handlers.ToArray();
// 清理所有数据结构
_pauseStacks.Clear();
_tokenMap.Clear();
@ -48,6 +60,34 @@ public class PauseStackManager : AbstractContextUtility, IPauseStackManager, IAs
_lock.ExitWriteLock();
}
// 在锁外通知所有之前暂停的组恢复,保持生命周期信号一致
foreach (var group in pausedGroups)
{
_logger.Debug($"Notifying handlers of destruction: Group={group}, IsPaused=false");
foreach (var handler in handlersSnapshot.OrderBy(h => h.Priority))
{
try
{
handler.OnPauseStateChanged(group, false);
}
catch (Exception ex)
{
_logger.Error($"Handler {handler.GetType().Name} failed during destruction", ex);
}
}
// 触发事件
try
{
OnPauseStateChanged?.Invoke(group, false);
}
catch (Exception ex)
{
_logger.Error($"Event subscriber failed during destruction for group {group}", ex);
}
}
// 释放锁资源
_lock.Dispose();
@ -422,8 +462,20 @@ public class PauseStackManager : AbstractContextUtility, IPauseStackManager, IAs
{
_logger.Debug($"Notifying handlers: Group={group}, IsPaused={isPaused}");
// 按优先级排序后通知
foreach (var handler in _handlers.OrderBy(h => h.Priority))
// 在锁内获取处理器快照,避免并发修改异常
IPauseHandler[] handlersSnapshot;
_lock.EnterReadLock();
try
{
handlersSnapshot = _handlers.OrderBy(h => h.Priority).ToArray();
}
finally
{
_lock.ExitReadLock();
}
// 在锁外遍历快照并通知处理器
foreach (var handler in handlersSnapshot)
{
try
{

View File

@ -1,5 +1,6 @@
**/*.Tests.cs
**/*.Test.cs
**/*.Tests.cs
**/*Test.cs
**/tests/**
**/*Tests.cs
**/Tests/**
**/*.Tests/**
**/*.Test/**