using System.Collections.Concurrent; using Serein.NodeFlow; using Serein.NodeFlow.Model; namespace Serein.NodeFlow.Tool { public class TcsSignalException : Exception { public FlowStateType FsState { get; set; } public TcsSignalException(string? message) : base(message) { FsState = FlowStateType.Error; } } public class TcsSignal where TSignal : struct, Enum { public ConcurrentDictionary>> TcsEvent { get; } = new(); // public object tcsObj = new object(); public bool TriggerSignal(TSignal signal, T state) { if (TcsEvent.TryRemove(signal, out var waitTcss)) { while (waitTcss.Count > 0) { waitTcss.Pop().SetResult(state); } return true; } return false; } public TaskCompletionSource CreateTcs(TSignal signal) { var tcs = new TaskCompletionSource(); TcsEvent.GetOrAdd(signal, _ => new Stack>()).Push(tcs); return tcs; } //public TaskCompletionSource GetOrCreateTcs(TSignal signal) //{ // lock (tcsObj) // { // var tcs = TcsEvent.GetOrAdd(signal, _ => new TaskCompletionSource()); // if (tcs.Task.IsCompleted) // { // TcsEvent.TryRemove(signal, out _); // tcs = new TaskCompletionSource(); // TcsEvent[signal] = tcs; // } // return tcs; // } //} public void CancelTask() { lock (TcsEvent) { foreach (var tcss in TcsEvent.Values) { while (tcss.Count > 0) { tcss.Pop().SetException(new TcsSignalException("Task Cancel")); } } TcsEvent.Clear(); } } } }