using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Serein.Flow.Tool { public class TcsSignalException : Exception { public FfState FfState { get; set; } public TcsSignalException(string? message) : base(message) { FfState = FfState.Cancel; } } 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(); } } } }