2 // System.Threading.WaitHandle.cs
5 // Dick Porter (dick@ximian.com)
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com
8 // (C) 2002,2003 Ximian, Inc. (http://www.ximian.com)
9 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Reflection;
33 using System.Runtime.CompilerServices;
34 using System.Runtime.Remoting.Contexts;
35 using System.Security.Permissions;
37 namespace System.Threading
39 public abstract class WaitHandle : MarshalByRefObject, IDisposable
41 [MethodImplAttribute(MethodImplOptions.InternalCall)]
42 private static extern bool WaitAll_internal(WaitHandle[] handles, int ms, bool exitContext);
44 static void CheckArray (WaitHandle [] handles, bool waitAll)
47 throw new ArgumentNullException ("waitHandles");
49 int length = handles.Length;
51 throw new NotSupportedException ("Too many handles");
53 if (waitAll && length > 1 &&
54 (Thread.CurrentThread.ApartmentState == ApartmentState.STA ||
55 Assembly.GetEntryAssembly ().EntryPoint.GetCustomAttributes (typeof (STAThreadAttribute), false).Length == 1))
56 throw new NotSupportedException ("WaitAll for multiple handles is not allowed on an STA thread.");
58 foreach (WaitHandle w in handles) {
60 throw new ArgumentNullException ("waitHandles", "null handle");
62 if (w.os_handle == InvalidHandle)
63 throw new ArgumentException ("null element found", "waitHandle");
67 public static bool WaitAll(WaitHandle[] waitHandles)
69 CheckArray (waitHandles, true);
70 return(WaitAll_internal(waitHandles, Timeout.Infinite, false));
73 public static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
75 CheckArray (waitHandles, true);
77 if (exitContext) SynchronizationAttribute.ExitContext ();
78 return(WaitAll_internal(waitHandles, millisecondsTimeout, false));
81 if (exitContext) SynchronizationAttribute.EnterContext ();
85 public static bool WaitAll(WaitHandle[] waitHandles,
89 CheckArray (waitHandles, true);
90 long ms = (long) timeout.TotalMilliseconds;
92 if (ms < -1 || ms > Int32.MaxValue)
93 throw new ArgumentOutOfRangeException ("timeout");
96 if (exitContext) SynchronizationAttribute.ExitContext ();
97 return (WaitAll_internal (waitHandles, (int) ms, exitContext));
100 if (exitContext) SynchronizationAttribute.EnterContext ();
104 [MethodImplAttribute(MethodImplOptions.InternalCall)]
105 private static extern int WaitAny_internal(WaitHandle[] handles, int ms, bool exitContext);
107 // LAMESPEC: Doesn't specify how to signal failures
108 public static int WaitAny(WaitHandle[] waitHandles)
110 CheckArray (waitHandles, false);
111 return(WaitAny_internal(waitHandles, Timeout.Infinite, false));
114 public static int WaitAny(WaitHandle[] waitHandles,
115 int millisecondsTimeout,
118 CheckArray (waitHandles, false);
120 if (exitContext) SynchronizationAttribute.ExitContext ();
121 return(WaitAny_internal(waitHandles, millisecondsTimeout, exitContext));
124 if (exitContext) SynchronizationAttribute.EnterContext ();
128 public static int WaitAny(WaitHandle[] waitHandles,
129 TimeSpan timeout, bool exitContext)
131 CheckArray (waitHandles, false);
132 long ms = (long) timeout.TotalMilliseconds;
134 if (ms < -1 || ms > Int32.MaxValue)
135 throw new ArgumentOutOfRangeException ("timeout");
138 if (exitContext) SynchronizationAttribute.ExitContext ();
139 return (WaitAny_internal(waitHandles, (int) ms, exitContext));
142 if (exitContext) SynchronizationAttribute.EnterContext ();
147 public WaitHandle() {
151 public const int WaitTimeout = 258;
153 private IntPtr os_handle = InvalidHandle;
155 public virtual IntPtr Handle {
160 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
161 [SecurityPermission (SecurityAction.InheritanceDemand, UnmanagedCode = true)]
167 public virtual void Close() {
169 GC.SuppressFinalize (this);
172 internal void CheckDisposed ()
174 if (disposed || os_handle == InvalidHandle)
175 throw new ObjectDisposedException (GetType ().FullName);
178 [MethodImplAttribute(MethodImplOptions.InternalCall)]
179 private extern bool WaitOne_internal(IntPtr handle, int ms, bool exitContext);
181 public virtual bool WaitOne()
184 return(WaitOne_internal(os_handle, Timeout.Infinite, false));
187 public virtual bool WaitOne(int millisecondsTimeout, bool exitContext)
191 if (exitContext) SynchronizationAttribute.ExitContext ();
192 return(WaitOne_internal(os_handle, millisecondsTimeout, exitContext));
195 if (exitContext) SynchronizationAttribute.EnterContext ();
199 public virtual bool WaitOne(TimeSpan timeout, bool exitContext)
202 long ms = (long) timeout.TotalMilliseconds;
203 if (ms < -1 || ms > Int32.MaxValue)
204 throw new ArgumentOutOfRangeException ("timeout");
207 if (exitContext) SynchronizationAttribute.ExitContext ();
208 return (WaitOne_internal(os_handle, (int) ms, exitContext));
211 if (exitContext) SynchronizationAttribute.EnterContext ();
215 protected static readonly IntPtr InvalidHandle = IntPtr.Zero;
217 bool disposed = false;
219 void IDisposable.Dispose() {
221 // Take yourself off the Finalization queue
222 GC.SuppressFinalize(this);
225 protected virtual void Dispose(bool explicitDisposing) {
226 // Check to see if Dispose has already been called.
229 if (os_handle == InvalidHandle)
233 if (os_handle != InvalidHandle) {
234 NativeEventCalls.CloseEvent_internal (os_handle);
235 os_handle = InvalidHandle;