#if !NETSTANDARD1_3 namespace Unosquare.Swan.Components { using System; using System.Threading; using Abstractions; /// /// Provides a Manual Reset Event factory with a unified API. /// /// /// The following example shows how to use the WaitEventFactory class. /// /// using Unosquare.Swan.Components; /// /// public class Example /// { /// // create a WaitEvent using the slim version /// private static readonly IWaitEvent waitEvent = WaitEventFactory.CreateSlim(false); /// /// public static void Main() /// { /// Task.Factory.StartNew(() => /// { /// DoWork(1); /// }); /// /// Task.Factory.StartNew(() => /// { /// DoWork(2); /// }); /// /// // send first signal /// waitEvent.Complete(); /// waitEvent.Begin(); /// /// Thread.Sleep(TimeSpan.FromSeconds(2)); /// /// // send second signal /// waitEvent.Complete(); /// /// Console.Readline(); /// } /// /// public static void DoWork(int taskNumber) /// { /// $"Data retrieved:{taskNumber}".WriteLine(); /// waitEvent.Wait(); /// /// Thread.Sleep(TimeSpan.FromSeconds(2)); /// $"All finished up {taskNumber}".WriteLine(); /// } /// } /// /// public static class WaitEventFactory { #region Factory Methods /// /// Creates a Wait Event backed by a standard ManualResetEvent. /// /// if initially set to completed. Generally true. /// The Wait Event. public static IWaitEvent Create(bool isCompleted) => new WaitEvent(isCompleted); /// /// Creates a Wait Event backed by a ManualResetEventSlim. /// /// if initially set to completed. Generally true. /// The Wait Event. public static IWaitEvent CreateSlim(bool isCompleted) => new WaitEventSlim(isCompleted); /// /// Creates a Wait Event backed by a ManualResetEventSlim. /// /// if initially set to completed. Generally true. /// if set to true creates a slim version of the wait event. /// The Wait Event. public static IWaitEvent Create(bool isCompleted, bool useSlim) => useSlim ? CreateSlim(isCompleted) : Create(isCompleted); #endregion #region Backing Classes /// /// Defines a WaitEvent backed by a ManualResetEvent. /// private class WaitEvent : IWaitEvent { private ManualResetEvent _event; /// /// Initializes a new instance of the class. /// /// if set to true [is completed]. public WaitEvent(bool isCompleted) { _event = new ManualResetEvent(isCompleted); } /// public bool IsDisposed { get; private set; } /// public bool IsValid { get { if (IsDisposed || _event == null) return false; if (_event?.SafeWaitHandle?.IsClosed ?? true) return false; return !(_event?.SafeWaitHandle?.IsInvalid ?? true); } } /// public bool IsCompleted { get { if (IsValid == false) return true; return _event?.WaitOne(0) ?? true; } } /// public bool IsInProgress => !IsCompleted; /// public void Begin() => _event?.Reset(); /// public void Complete() => _event?.Set(); /// void IDisposable.Dispose() { if (IsDisposed) return; IsDisposed = true; _event?.Set(); _event?.Dispose(); _event = null; } /// public void Wait() => _event?.WaitOne(); /// public bool Wait(TimeSpan timeout) => _event?.WaitOne(timeout) ?? true; } /// /// Defines a WaitEvent backed by a ManualResetEventSlim. /// private class WaitEventSlim : IWaitEvent { private ManualResetEventSlim _event; /// /// Initializes a new instance of the class. /// /// if set to true [is completed]. public WaitEventSlim(bool isCompleted) { _event = new ManualResetEventSlim(isCompleted); } /// public bool IsDisposed { get; private set; } /// public bool IsValid { get { if (IsDisposed || _event?.WaitHandle?.SafeWaitHandle == null) return false; return !_event.WaitHandle.SafeWaitHandle.IsClosed && !_event.WaitHandle.SafeWaitHandle.IsInvalid; } } /// public bool IsCompleted => IsValid == false || _event.IsSet; /// public bool IsInProgress => !IsCompleted; /// public void Begin() => _event?.Reset(); /// public void Complete() => _event?.Set(); /// void IDisposable.Dispose() { if (IsDisposed) return; IsDisposed = true; _event?.Set(); _event?.Dispose(); _event = null; } /// public void Wait() => _event?.Wait(); /// public bool Wait(TimeSpan timeout) => _event?.Wait(timeout) ?? true; } #endregion } } #endif