using System.Threading; namespace SimpleAdmin.Application; /// /// 使同一异步调用链可重入,独立请求仍须取得外部互斥锁。 /// 不在 Acquire 中设置 AsyncLocal,避免值不能流回调用方的问题。 /// internal static class OnboardingOperationGate { private sealed record Frame(string Key, Frame Parent); private static readonly AsyncLocal Held = new(); internal static async Task Run( string key, Func> acquire, Func> action) { for (var frame = Held.Value; frame != null; frame = frame.Parent) if (frame.Key == key) return await action(); await using var lease = await acquire(); var previous = Held.Value; Held.Value = new Frame(key, previous); try { return await action(); } finally { Held.Value = previous; } } }