using System;
using System.Threading;
namespace PaintDotNet.SystemLayer
{
///
/// Encapsulates an array of WaitHandles and methods for waiting on them.
/// This class does not take ownership of the WaitHandles; you must still
/// Dispose() them yourself.
///
///
/// This class exists because System.Threading.WaitHandle.Wait[Any|All] will throw an exception
/// in an STA apartment. So we must P/Invoke down to WaitForMultipleObjects().
///
public sealed class WaitHandleArray
{
private WaitHandle[] waitHandles;
private IntPtr[] nativeHandles;
///
/// The minimum value that may be passed to the constructor for initialization.
///
public const int MinimumCount = 1;
///
/// The maximum value that may be passed to the construct for initialization.
///
public const int MaximumCount = 64; // WaitForMultipleObjects() can only wait on up to 64 objects at once
///
/// Gets or sets the WaitHandle at the specified index.
///
public WaitHandle this[int index]
{
get
{
return this.waitHandles[index];
}
set
{
this.waitHandles[index] = value;
this.nativeHandles[index] = value.SafeWaitHandle.DangerousGetHandle();
}
}
///
/// Gets the length of the array.
///
public int Length
{
get
{
return this.waitHandles.Length;
}
}
///
/// Initializes a new instance of the WaitHandleArray class.
///
/// The size of the array.
public WaitHandleArray(int count)
{
if (count < 1 || count > 64)
{
throw new ArgumentOutOfRangeException("count", "must be between 1 and 64, inclusive");
}
this.waitHandles = new WaitHandle[count];
this.nativeHandles = new IntPtr[count];
}
private uint WaitForAll(uint dwTimeout)
{
return SafeNativeMethods.WaitForMultipleObjects(this.nativeHandles, true, dwTimeout);
}
///
/// Waits for all of the WaitHandles to be signaled.
///
public void WaitAll()
{
WaitForAll(NativeConstants.INFINITE);
}
public bool AreAllSignaled()
{
return AreAllSignaled(0);
}
public bool AreAllSignaled(uint msTimeout)
{
uint result = WaitForAll(msTimeout);
if (result >= NativeConstants.WAIT_OBJECT_0 && result < NativeConstants.WAIT_OBJECT_0 + this.Length)
{
return true;
}
else
{
return false;
}
}
///
/// Waits for any of the WaitHandles to be signaled.
///
///
/// The index of the first item in the array that completed the wait operation.
/// If this value is outside the bounds of the array, it is an indication of an
/// error.
///
public int WaitAny()
{
int returnVal = (int)SafeNativeMethods.WaitForMultipleObjects(this.nativeHandles, false, NativeConstants.INFINITE);
return returnVal;
}
}
}