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 && IsSTAThread)
54 throw new NotSupportedException ("WaitAll for multiple handles is not allowed on an STA thread.");
56 foreach (WaitHandle w in handles) {
58 throw new ArgumentNullException ("waitHandles", "null handle");
60 if (w.os_handle == InvalidHandle)
61 throw new ArgumentException ("null element found", "waitHandle");
65 static bool IsSTAThread {
67 bool isSTA = Thread.CurrentThread.ApartmentState ==
70 // FIXME: remove this check after Thread.ApartmentState
71 // has been properly implemented.
73 Assembly asm = Assembly.GetEntryAssembly ();
75 isSTA = asm.EntryPoint.GetCustomAttributes (typeof (STAThreadAttribute), false).Length > 0;
82 public static bool WaitAll(WaitHandle[] waitHandles)
84 CheckArray (waitHandles, true);
85 return(WaitAll_internal(waitHandles, Timeout.Infinite, false));
88 public static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
90 CheckArray (waitHandles, true);
92 if (exitContext) SynchronizationAttribute.ExitContext ();
93 return(WaitAll_internal(waitHandles, millisecondsTimeout, false));
96 if (exitContext) SynchronizationAttribute.EnterContext ();
100 public static bool WaitAll(WaitHandle[] waitHandles,
104 CheckArray (waitHandles, true);
105 long ms = (long) timeout.TotalMilliseconds;
107 if (ms < -1 || ms > Int32.MaxValue)
108 throw new ArgumentOutOfRangeException ("timeout");
111 if (exitContext) SynchronizationAttribute.ExitContext ();
112 return (WaitAll_internal (waitHandles, (int) ms, exitContext));
115 if (exitContext) SynchronizationAttribute.EnterContext ();
119 [MethodImplAttribute(MethodImplOptions.InternalCall)]
120 private static extern int WaitAny_internal(WaitHandle[] handles, int ms, bool exitContext);
122 // LAMESPEC: Doesn't specify how to signal failures
123 public static int WaitAny(WaitHandle[] waitHandles)
125 CheckArray (waitHandles, false);
126 return(WaitAny_internal(waitHandles, Timeout.Infinite, false));
129 public static int WaitAny(WaitHandle[] waitHandles,
130 int millisecondsTimeout,
133 CheckArray (waitHandles, false);
135 if (exitContext) SynchronizationAttribute.ExitContext ();
136 return(WaitAny_internal(waitHandles, millisecondsTimeout, exitContext));
139 if (exitContext) SynchronizationAttribute.EnterContext ();
143 public static int WaitAny(WaitHandle[] waitHandles,
144 TimeSpan timeout, bool exitContext)
146 CheckArray (waitHandles, false);
147 long ms = (long) timeout.TotalMilliseconds;
149 if (ms < -1 || ms > Int32.MaxValue)
150 throw new ArgumentOutOfRangeException ("timeout");
153 if (exitContext) SynchronizationAttribute.ExitContext ();
154 return (WaitAny_internal(waitHandles, (int) ms, exitContext));
157 if (exitContext) SynchronizationAttribute.EnterContext ();
162 public WaitHandle() {
166 public const int WaitTimeout = 258;
168 private IntPtr os_handle = InvalidHandle;
170 public virtual IntPtr Handle {
175 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
176 [SecurityPermission (SecurityAction.InheritanceDemand, UnmanagedCode = true)]
182 public virtual void Close() {
184 GC.SuppressFinalize (this);
187 internal void CheckDisposed ()
189 if (disposed || os_handle == InvalidHandle)
190 throw new ObjectDisposedException (GetType ().FullName);
193 [MethodImplAttribute(MethodImplOptions.InternalCall)]
194 private extern bool WaitOne_internal(IntPtr handle, int ms, bool exitContext);
196 public virtual bool WaitOne()
199 return(WaitOne_internal(os_handle, Timeout.Infinite, false));
202 public virtual bool WaitOne(int millisecondsTimeout, bool exitContext)
206 if (exitContext) SynchronizationAttribute.ExitContext ();
207 return(WaitOne_internal(os_handle, millisecondsTimeout, exitContext));
210 if (exitContext) SynchronizationAttribute.EnterContext ();
214 public virtual bool WaitOne(TimeSpan timeout, bool exitContext)
217 long ms = (long) timeout.TotalMilliseconds;
218 if (ms < -1 || ms > Int32.MaxValue)
219 throw new ArgumentOutOfRangeException ("timeout");
222 if (exitContext) SynchronizationAttribute.ExitContext ();
223 return (WaitOne_internal(os_handle, (int) ms, exitContext));
226 if (exitContext) SynchronizationAttribute.EnterContext ();
230 protected static readonly IntPtr InvalidHandle = IntPtr.Zero;
232 bool disposed = false;
234 void IDisposable.Dispose() {
236 // Take yourself off the Finalization queue
237 GC.SuppressFinalize(this);
240 protected virtual void Dispose(bool explicitDisposing) {
241 // Check to see if Dispose has already been called.
244 if (os_handle == InvalidHandle)
248 if (os_handle != InvalidHandle) {
249 NativeEventCalls.CloseEvent_internal (os_handle);
250 os_handle = InvalidHandle;