WaitHandleArray.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. using System;
  2. using System.Threading;
  3. namespace PaintDotNet.SystemLayer
  4. {
  5. /// <summary>
  6. /// Encapsulates an array of WaitHandles and methods for waiting on them.
  7. /// This class does not take ownership of the WaitHandles; you must still
  8. /// Dispose() them yourself.
  9. /// </summary>
  10. /// <remarks>
  11. /// This class exists because System.Threading.WaitHandle.Wait[Any|All] will throw an exception
  12. /// in an STA apartment. So we must P/Invoke down to WaitForMultipleObjects().
  13. /// </remarks>
  14. public sealed class WaitHandleArray
  15. {
  16. private WaitHandle[] waitHandles;
  17. private IntPtr[] nativeHandles;
  18. /// <summary>
  19. /// The minimum value that may be passed to the constructor for initialization.
  20. /// </summary>
  21. public const int MinimumCount = 1;
  22. /// <summary>
  23. /// The maximum value that may be passed to the construct for initialization.
  24. /// </summary>
  25. public const int MaximumCount = 64; // WaitForMultipleObjects() can only wait on up to 64 objects at once
  26. /// <summary>
  27. /// Gets or sets the WaitHandle at the specified index.
  28. /// </summary>
  29. public WaitHandle this[int index]
  30. {
  31. get
  32. {
  33. return this.waitHandles[index];
  34. }
  35. set
  36. {
  37. this.waitHandles[index] = value;
  38. this.nativeHandles[index] = value.SafeWaitHandle.DangerousGetHandle();
  39. }
  40. }
  41. /// <summary>
  42. /// Gets the length of the array.
  43. /// </summary>
  44. public int Length
  45. {
  46. get
  47. {
  48. return this.waitHandles.Length;
  49. }
  50. }
  51. /// <summary>
  52. /// Initializes a new instance of the WaitHandleArray class.
  53. /// </summary>
  54. /// <param name="count">The size of the array.</param>
  55. public WaitHandleArray(int count)
  56. {
  57. if (count < 1 || count > 64)
  58. {
  59. throw new ArgumentOutOfRangeException("count", "must be between 1 and 64, inclusive");
  60. }
  61. this.waitHandles = new WaitHandle[count];
  62. this.nativeHandles = new IntPtr[count];
  63. }
  64. private uint WaitForAll(uint dwTimeout)
  65. {
  66. return SafeNativeMethods.WaitForMultipleObjects(this.nativeHandles, true, dwTimeout);
  67. }
  68. /// <summary>
  69. /// Waits for all of the WaitHandles to be signaled.
  70. /// </summary>
  71. public void WaitAll()
  72. {
  73. WaitForAll(NativeConstants.INFINITE);
  74. }
  75. public bool AreAllSignaled()
  76. {
  77. return AreAllSignaled(0);
  78. }
  79. public bool AreAllSignaled(uint msTimeout)
  80. {
  81. uint result = WaitForAll(msTimeout);
  82. if (result >= NativeConstants.WAIT_OBJECT_0 && result < NativeConstants.WAIT_OBJECT_0 + this.Length)
  83. {
  84. return true;
  85. }
  86. else
  87. {
  88. return false;
  89. }
  90. }
  91. /// <summary>
  92. /// Waits for any of the WaitHandles to be signaled.
  93. /// </summary>
  94. /// <returns>
  95. /// The index of the first item in the array that completed the wait operation.
  96. /// If this value is outside the bounds of the array, it is an indication of an
  97. /// error.
  98. /// </returns>
  99. public int WaitAny()
  100. {
  101. int returnVal = (int)SafeNativeMethods.WaitForMultipleObjects(this.nativeHandles, false, NativeConstants.INFINITE);
  102. return returnVal;
  103. }
  104. }
  105. }