196 lines
6.0 KiB
C#
196 lines
6.0 KiB
C#
|
|
|
|
#if !NETSTANDARD1_3
|
|
using System;
|
|
using System.Threading;
|
|
using Unosquare.Swan.Abstractions;
|
|
namespace Unosquare.Swan.Components {
|
|
/// <summary>
|
|
/// Provides a Manual Reset Event factory with a unified API.
|
|
/// </summary>
|
|
/// <example>
|
|
/// The following example shows how to use the WaitEventFactory class.
|
|
/// <code>
|
|
/// 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();
|
|
/// }
|
|
/// }
|
|
/// </code>
|
|
/// </example>
|
|
public static class WaitEventFactory {
|
|
#region Factory Methods
|
|
|
|
/// <summary>
|
|
/// Creates a Wait Event backed by a standard ManualResetEvent.
|
|
/// </summary>
|
|
/// <param name="isCompleted">if initially set to completed. Generally true.</param>
|
|
/// <returns>The Wait Event.</returns>
|
|
public static IWaitEvent Create(Boolean isCompleted) => new WaitEvent(isCompleted);
|
|
|
|
/// <summary>
|
|
/// Creates a Wait Event backed by a ManualResetEventSlim.
|
|
/// </summary>
|
|
/// <param name="isCompleted">if initially set to completed. Generally true.</param>
|
|
/// <returns>The Wait Event.</returns>
|
|
public static IWaitEvent CreateSlim(Boolean isCompleted) => new WaitEventSlim(isCompleted);
|
|
|
|
/// <summary>
|
|
/// Creates a Wait Event backed by a ManualResetEventSlim.
|
|
/// </summary>
|
|
/// <param name="isCompleted">if initially set to completed. Generally true.</param>
|
|
/// <param name="useSlim">if set to <c>true</c> creates a slim version of the wait event.</param>
|
|
/// <returns>The Wait Event.</returns>
|
|
public static IWaitEvent Create(Boolean isCompleted, Boolean useSlim) => useSlim ? CreateSlim(isCompleted) : Create(isCompleted);
|
|
|
|
#endregion
|
|
|
|
#region Backing Classes
|
|
|
|
/// <summary>
|
|
/// Defines a WaitEvent backed by a ManualResetEvent.
|
|
/// </summary>
|
|
private class WaitEvent : IWaitEvent {
|
|
private ManualResetEvent _event;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="WaitEvent"/> class.
|
|
/// </summary>
|
|
/// <param name="isCompleted">if set to <c>true</c> [is completed].</param>
|
|
public WaitEvent(Boolean isCompleted) => this._event = new ManualResetEvent(isCompleted);
|
|
|
|
/// <inheritdoc />
|
|
public Boolean IsDisposed {
|
|
get; private set;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Boolean IsValid => this.IsDisposed || this._event == null
|
|
? false
|
|
: this._event?.SafeWaitHandle?.IsClosed ?? true ? false : !(this._event?.SafeWaitHandle?.IsInvalid ?? true);
|
|
|
|
/// <inheritdoc />
|
|
public Boolean IsCompleted => this.IsValid == false ? true : this._event?.WaitOne(0) ?? true;
|
|
|
|
/// <inheritdoc />
|
|
public Boolean IsInProgress => !this.IsCompleted;
|
|
|
|
/// <inheritdoc />
|
|
public void Begin() => this._event?.Reset();
|
|
|
|
/// <inheritdoc />
|
|
public void Complete() => this._event?.Set();
|
|
|
|
/// <inheritdoc />
|
|
void IDisposable.Dispose() {
|
|
if(this.IsDisposed) {
|
|
return;
|
|
}
|
|
|
|
this.IsDisposed = true;
|
|
|
|
_ = this._event?.Set();
|
|
this._event?.Dispose();
|
|
this._event = null;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void Wait() => this._event?.WaitOne();
|
|
|
|
/// <inheritdoc />
|
|
public Boolean Wait(TimeSpan timeout) => this._event?.WaitOne(timeout) ?? true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Defines a WaitEvent backed by a ManualResetEventSlim.
|
|
/// </summary>
|
|
private class WaitEventSlim : IWaitEvent {
|
|
private ManualResetEventSlim _event;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="WaitEventSlim"/> class.
|
|
/// </summary>
|
|
/// <param name="isCompleted">if set to <c>true</c> [is completed].</param>
|
|
public WaitEventSlim(Boolean isCompleted) => this._event = new ManualResetEventSlim(isCompleted);
|
|
|
|
/// <inheritdoc />
|
|
public Boolean IsDisposed {
|
|
get; private set;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Boolean IsValid => this.IsDisposed || this._event?.WaitHandle?.SafeWaitHandle == null
|
|
? false
|
|
: !this._event.WaitHandle.SafeWaitHandle.IsClosed && !this._event.WaitHandle.SafeWaitHandle.IsInvalid;
|
|
|
|
/// <inheritdoc />
|
|
public Boolean IsCompleted => this.IsValid == false || this._event.IsSet;
|
|
|
|
/// <inheritdoc />
|
|
public Boolean IsInProgress => !this.IsCompleted;
|
|
|
|
/// <inheritdoc />
|
|
public void Begin() => this._event?.Reset();
|
|
|
|
/// <inheritdoc />
|
|
public void Complete() => this._event?.Set();
|
|
|
|
/// <inheritdoc />
|
|
void IDisposable.Dispose() {
|
|
if(this.IsDisposed) {
|
|
return;
|
|
}
|
|
|
|
this.IsDisposed = true;
|
|
|
|
this._event?.Set();
|
|
this._event?.Dispose();
|
|
this._event = null;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void Wait() => this._event?.Wait();
|
|
|
|
/// <inheritdoc />
|
|
public Boolean Wait(TimeSpan timeout) => this._event?.Wait(timeout) ?? true;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|
|
#endif |