using System.Collections.Generic; using ScreenConnect; namespace System.Threading; public class CancellationTokenSource : IDisposable { private object syncLock = new object(); private bool isCancellationRequested; private IList? actions; private CancellationTokenRegistration[] linkedRegistrations; private ManualResetEvent? waitHandle; public bool IsCancellationRequested => isCancellationRequested; public CancellationToken Token => new CancellationToken(this); public WaitHandle WaitHandle { get { if (waitHandle == null) { lock (syncLock) { if (waitHandle == null) { waitHandle = new ManualResetEvent(isCancellationRequested); } } } return waitHandle; } } public CancellationTokenSource() { linkedRegistrations = Extensions.EmptyArray(); } private CancellationTokenSource(CancellationToken[] linkedTokens) { linkedRegistrations = linkedTokens.SelectToArray((CancellationToken it) => it.Register(this.TryCancel)); } public void Cancel() { if (isCancellationRequested) { return; } lock (syncLock) { if (IsCancellationRequested) { return; } isCancellationRequested = true; if (waitHandle != null) { waitHandle.Set(); } ScreenConnect.Lazy> lazy = Lazy.Create(() => new List()); foreach (Action item2 in actions.SafeEnumerate()) { try { item2(); } catch (Exception item) { lazy.Value.Add(item); } } if (lazy.HasResolvedValue) { throw new AggregateException(lazy.Value); } } } internal CancellationTokenRegistration Register(Action action) { lock (syncLock) { if (isCancellationRequested) { action(); return default(CancellationTokenRegistration); } Extensions.AddSafe(ref actions, action); return new CancellationTokenRegistration { CancellationTokenSource = this, Action = action }; } } internal void Unregister(Action action) { lock (syncLock) { actions?.Remove(action); } } public static CancellationTokenSource CreateLinkedTokenSource(CancellationToken token1, CancellationToken token2) { return CreateLinkedTokenSource(new CancellationToken[2] { token1, token2 }); } public static CancellationTokenSource CreateLinkedTokenSource(params CancellationToken[] tokens) { return new CancellationTokenSource(tokens); } public void Dispose() { lock (syncLock) { linkedRegistrations.DisposeQuietly(); waitHandle?.DisposeQuietly(); } } }