WaitHandle.WaitAny Method
Definition
Important
Some information relates to prerelease product that may be substantially modified before it’s released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
Waits for any of the elements in the specified array to receive a signal.
Overloads
WaitAny(WaitHandle[]) |
Waits for any of the elements in the specified array to receive a signal. |
WaitAny(WaitHandle[], Int32) |
Waits for any of the elements in the specified array to receive a signal, using a 32-bit signed integer to specify the time interval. |
WaitAny(WaitHandle[], TimeSpan) |
Waits for any of the elements in the specified array to receive a signal, using a TimeSpan to specify the time interval. |
WaitAny(WaitHandle[], Int32, Boolean) |
Waits for any of the elements in the specified array to receive a signal, using a 32-bit signed integer to specify the time interval, and specifying whether to exit the synchronization domain before the wait. |
WaitAny(WaitHandle[], TimeSpan, Boolean) |
Waits for any of the elements in the specified array to receive a signal, using a TimeSpan to specify the time interval and specifying whether to exit the synchronization domain before the wait. |
WaitAny(WaitHandle[])
- Source:
- WaitHandle.cs
- Source:
- WaitHandle.cs
- Source:
- WaitHandle.cs
Waits for any of the elements in the specified array to receive a signal.
public:
static int WaitAny(cli::array <System::Threading::WaitHandle ^> ^ waitHandles);
public static int WaitAny (System.Threading.WaitHandle[] waitHandles);
static member WaitAny : System.Threading.WaitHandle[] -> int
Public Shared Function WaitAny (waitHandles As WaitHandle()) As Integer
Parameters
- waitHandles
- WaitHandle[]
A WaitHandle
array containing the objects for which the current instance will wait.
Returns
The array index of the object that satisfied the wait.
Exceptions
The waitHandles
parameter is null
.
-or-
One or more of the objects in the waitHandles
array is null
.
The number of objects in waitHandles
is greater than the system permits.
waitHandles
is an array with no elements, and the .NET Framework version is 1.0 or 1.1.
The wait completed because a thread exited without releasing a mutex.
waitHandles
is an array with no elements, and the .NET Framework version is 2.0 or later.
The waitHandles
array contains a transparent proxy for a WaitHandle in another application domain.
Examples
The following code example demonstrates calling the WaitAny method.
using namespace System;
using namespace System::Threading;
public ref class WaitHandleExample
{
// Define a random number generator for testing.
private:
static Random^ random = gcnew Random();
public:
static void DoTask(Object^ state)
{
AutoResetEvent^ autoReset = (AutoResetEvent^) state;
int time = 1000 * random->Next(2, 10);
Console::WriteLine("Performing a task for {0} milliseconds.", time);
Thread::Sleep(time);
autoReset->Set();
}
};
int main()
{
// Define an array with two AutoResetEvent WaitHandles.
array<WaitHandle^>^ handles = gcnew array<WaitHandle^> {
gcnew AutoResetEvent(false), gcnew AutoResetEvent(false)};
// Queue up two tasks on two different threads;
// wait until all tasks are completed.
DateTime timeInstance = DateTime::Now;
Console::WriteLine("Main thread is waiting for BOTH tasks to " +
"complete.");
ThreadPool::QueueUserWorkItem(
gcnew WaitCallback(WaitHandleExample::DoTask), handles[0]);
ThreadPool::QueueUserWorkItem(
gcnew WaitCallback(WaitHandleExample::DoTask), handles[1]);
WaitHandle::WaitAll(handles);
// The time shown below should match the longest task.
Console::WriteLine("Both tasks are completed (time waited={0})",
(DateTime::Now - timeInstance).TotalMilliseconds);
// Queue up two tasks on two different threads;
// wait until any tasks are completed.
timeInstance = DateTime::Now;
Console::WriteLine();
Console::WriteLine("The main thread is waiting for either task to " +
"complete.");
ThreadPool::QueueUserWorkItem(
gcnew WaitCallback(WaitHandleExample::DoTask), handles[0]);
ThreadPool::QueueUserWorkItem(
gcnew WaitCallback(WaitHandleExample::DoTask), handles[1]);
int index = WaitHandle::WaitAny(handles);
// The time shown below should match the shortest task.
Console::WriteLine("Task {0} finished first (time waited={1}).",
index + 1, (DateTime::Now - timeInstance).TotalMilliseconds);
}
// This code produces the following sample output.
//
// Main thread is waiting for BOTH tasks to complete.
// Performing a task for 7000 milliseconds.
// Performing a task for 4000 milliseconds.
// Both tasks are completed (time waited=7064.8052)
// The main thread is waiting for either task to complete.
// Performing a task for 2000 milliseconds.
// Performing a task for 2000 milliseconds.
// Task 1 finished first (time waited=2000.6528).
using System;
using System.Threading;
public sealed class App
{
// Define an array with two AutoResetEvent WaitHandles.
static WaitHandle[] waitHandles = new WaitHandle[]
{
new AutoResetEvent(false),
new AutoResetEvent(false)
};
// Define a random number generator for testing.
static Random r = new Random();
static void Main()
{
// Queue up two tasks on two different threads;
// wait until all tasks are completed.
DateTime dt = DateTime.Now;
Console.WriteLine("Main thread is waiting for BOTH tasks to complete.");
ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[0]);
ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[1]);
WaitHandle.WaitAll(waitHandles);
// The time shown below should match the longest task.
Console.WriteLine("Both tasks are completed (time waited={0})",
(DateTime.Now - dt).TotalMilliseconds);
// Queue up two tasks on two different threads;
// wait until any task is completed.
dt = DateTime.Now;
Console.WriteLine();
Console.WriteLine("The main thread is waiting for either task to complete.");
ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[0]);
ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[1]);
int index = WaitHandle.WaitAny(waitHandles);
// The time shown below should match the shortest task.
Console.WriteLine("Task {0} finished first (time waited={1}).",
index + 1, (DateTime.Now - dt).TotalMilliseconds);
}
static void DoTask(Object state)
{
AutoResetEvent are = (AutoResetEvent) state;
int time = 1000 * r.Next(2, 10);
Console.WriteLine("Performing a task for {0} milliseconds.", time);
Thread.Sleep(time);
are.Set();
}
}
// This code produces output similar to the following:
//
// Main thread is waiting for BOTH tasks to complete.
// Performing a task for 7000 milliseconds.
// Performing a task for 4000 milliseconds.
// Both tasks are completed (time waited=7064.8052)
//
// The main thread is waiting for either task to complete.
// Performing a task for 2000 milliseconds.
// Performing a task for 2000 milliseconds.
// Task 1 finished first (time waited=2000.6528).
Imports System.Threading
NotInheritable Public Class App
' Define an array with two AutoResetEvent WaitHandles.
Private Shared waitHandles() As WaitHandle = _
{New AutoResetEvent(False), New AutoResetEvent(False)}
' Define a random number generator for testing.
Private Shared r As New Random()
<MTAThreadAttribute> _
Public Shared Sub Main()
' Queue two tasks on two different threads;
' wait until all tasks are completed.
Dim dt As DateTime = DateTime.Now
Console.WriteLine("Main thread is waiting for BOTH tasks to complete.")
ThreadPool.QueueUserWorkItem(AddressOf DoTask, waitHandles(0))
ThreadPool.QueueUserWorkItem(AddressOf DoTask, waitHandles(1))
WaitHandle.WaitAll(waitHandles)
' The time shown below should match the longest task.
Console.WriteLine("Both tasks are completed (time waited={0})", _
(DateTime.Now - dt).TotalMilliseconds)
' Queue up two tasks on two different threads;
' wait until any tasks are completed.
dt = DateTime.Now
Console.WriteLine()
Console.WriteLine("The main thread is waiting for either task to complete.")
ThreadPool.QueueUserWorkItem(AddressOf DoTask, waitHandles(0))
ThreadPool.QueueUserWorkItem(AddressOf DoTask, waitHandles(1))
Dim index As Integer = WaitHandle.WaitAny(waitHandles)
' The time shown below should match the shortest task.
Console.WriteLine("Task {0} finished first (time waited={1}).", _
index + 1,(DateTime.Now - dt).TotalMilliseconds)
End Sub
Shared Sub DoTask(ByVal state As [Object])
Dim are As AutoResetEvent = CType(state, AutoResetEvent)
Dim time As Integer = 1000 * r.Next(2, 10)
Console.WriteLine("Performing a task for {0} milliseconds.", time)
Thread.Sleep(time)
are.Set()
End Sub
End Class
' This code produces output similar to the following:
'
' Main thread is waiting for BOTH tasks to complete.
' Performing a task for 7000 milliseconds.
' Performing a task for 4000 milliseconds.
' Both tasks are completed (time waited=7064.8052)
'
' The main thread is waiting for either task to complete.
' Performing a task for 2000 milliseconds.
' Performing a task for 2000 milliseconds.
' Task 1 finished first (time waited=2000.6528).
Remarks
AbandonedMutexException is new in the .NET Framework version 2.0. In previous versions, the WaitAny method returns true
if the wait completes because a mutex is abandoned. An abandoned mutex often indicates a serious coding error. In the case of a system-wide mutex, it might indicate that an application has been terminated abruptly (for example, by using Windows Task Manager). The exception contains information useful for debugging.
The WaitAny method throws an AbandonedMutexException only when the wait completes because of an abandoned mutex. If waitHandles
contains a released mutex with a lower index number than the abandoned mutex, the WaitAny method completes normally and the exception is not thrown.
Note
In versions of the .NET Framework earlier than version 2.0, if a thread exits or aborts without explicitly releasing a Mutex, and that Mutex
is at index 0 (zero) in a WaitAny
array on another thread, the index returned by WaitAny
is 128 instead of 0.
This method returns when any handle is signaled. If more than one object becomes signaled during the call, the return value is the array index of the signaled object with the smallest index value of all the signaled objects.
The maximum number of the wait handles is 64, and 63 if the current thread is in STA state.
Calling this method overload is equivalent to calling the WaitAny(WaitHandle[], Int32, Boolean) method overload and specifying -1 (or Timeout.Infinite) for millisecondsTimeout
and true
for exitContext
.
Applies to
WaitAny(WaitHandle[], Int32)
- Source:
- WaitHandle.cs
- Source:
- WaitHandle.cs
- Source:
- WaitHandle.cs
Waits for any of the elements in the specified array to receive a signal, using a 32-bit signed integer to specify the time interval.
public:
static int WaitAny(cli::array <System::Threading::WaitHandle ^> ^ waitHandles, int millisecondsTimeout);
public static int WaitAny (System.Threading.WaitHandle[] waitHandles, int millisecondsTimeout);
static member WaitAny : System.Threading.WaitHandle[] * int -> int
Public Shared Function WaitAny (waitHandles As WaitHandle(), millisecondsTimeout As Integer) As Integer
Parameters
- waitHandles
- WaitHandle[]
A WaitHandle
array containing the objects for which the current instance will wait.
- millisecondsTimeout
- Int32
The number of milliseconds to wait, or Infinite (-1) to wait indefinitely.
Returns
The array index of the object that satisfied the wait, or WaitTimeout if no object satisfied the wait and a time interval equivalent to millisecondsTimeout
has passed.
Exceptions
The waitHandles
parameter is null
.
-or-
One or more of the objects in the waitHandles
array is null
.
The number of objects in waitHandles
is greater than the system permits.
millisecondsTimeout
is a negative number other than -1, which represents an infinite time-out.
The wait completed because a thread exited without releasing a mutex.
waitHandles
is an array with no elements.
The waitHandles
array contains a transparent proxy for a WaitHandle in another application domain.
Remarks
If millisecondsTimeout
is zero, the method does not block. It tests the state of the wait handles and returns immediately.
The WaitAny method throws an AbandonedMutexException only when the wait completes because of an abandoned mutex. If waitHandles
contains a released mutex with a lower index number than the abandoned mutex, the WaitAny method completes normally and the exception is not thrown.
This method returns when the wait terminates, either when any of the handles are signaled or when a timeout occurs. If more than one object becomes signaled during the call, the return value is the array index of the signaled object with the smallest index value of all the signaled objects.
The maximum number of the wait handles is 64, and 63 if the current thread is in STA state.
Calling this method overload is the same as calling the WaitAny(WaitHandle[], Int32, Boolean) overload and specifying false
for exitContext
.
Applies to
WaitAny(WaitHandle[], TimeSpan)
- Source:
- WaitHandle.cs
- Source:
- WaitHandle.cs
- Source:
- WaitHandle.cs
Waits for any of the elements in the specified array to receive a signal, using a TimeSpan to specify the time interval.
public:
static int WaitAny(cli::array <System::Threading::WaitHandle ^> ^ waitHandles, TimeSpan timeout);
public static int WaitAny (System.Threading.WaitHandle[] waitHandles, TimeSpan timeout);
static member WaitAny : System.Threading.WaitHandle[] * TimeSpan -> int
Public Shared Function WaitAny (waitHandles As WaitHandle(), timeout As TimeSpan) As Integer
Parameters
- waitHandles
- WaitHandle[]
A WaitHandle
array containing the objects for which the current instance will wait.
- timeout
- TimeSpan
A TimeSpan that represents the number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely.
Returns
The array index of the object that satisfied the wait, or WaitTimeout if no object satisfied the wait and a time interval equivalent to timeout
has passed.
Exceptions
The waitHandles
parameter is null
.
-or-
One or more of the objects in the waitHandles
array is null
.
The number of objects in waitHandles
is greater than the system permits.
timeout
is a negative number other than -1 milliseconds, which represents an infinite time-out.
-or-
timeout
is greater than Int32.MaxValue.
The wait completed because a thread exited without releasing a mutex.
waitHandles
is an array with no elements.
The waitHandles
array contains a transparent proxy for a WaitHandle in another application domain.
Remarks
If timeout
is zero, the method does not block. It tests the state of the wait handles and returns immediately.
The WaitAny method throws an AbandonedMutexException only when the wait completes because of an abandoned mutex. If waitHandles
contains a released mutex with a lower index number than the abandoned mutex, the WaitAny method completes normally and the exception is not thrown.
This method returns when the wait terminates, either when any of the handles are signaled or when a time-out occurs. If more than one object becomes signaled during the call, the return value is the array index of the signaled object with the smallest index value of all the signaled objects.
The maximum number of the wait handles is 64, and 63 if the current thread is in STA state.
The maximum value for timeout
is Int32.MaxValue.
Calling this method overload is the same as calling the WaitAny(WaitHandle[], TimeSpan, Boolean) overload and specifying false
for exitContext
.
Applies to
WaitAny(WaitHandle[], Int32, Boolean)
- Source:
- WaitHandle.cs
- Source:
- WaitHandle.cs
- Source:
- WaitHandle.cs
Waits for any of the elements in the specified array to receive a signal, using a 32-bit signed integer to specify the time interval, and specifying whether to exit the synchronization domain before the wait.
public:
static int WaitAny(cli::array <System::Threading::WaitHandle ^> ^ waitHandles, int millisecondsTimeout, bool exitContext);
public static int WaitAny (System.Threading.WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext);
static member WaitAny : System.Threading.WaitHandle[] * int * bool -> int
Public Shared Function WaitAny (waitHandles As WaitHandle(), millisecondsTimeout As Integer, exitContext As Boolean) As Integer
Parameters
- waitHandles
- WaitHandle[]
A WaitHandle
array containing the objects for which the current instance will wait.
- millisecondsTimeout
- Int32
The number of milliseconds to wait, or Infinite (-1) to wait indefinitely.
- exitContext
- Boolean
true
to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it afterward; otherwise, false
.
Returns
The array index of the object that satisfied the wait, or WaitTimeout if no object satisfied the wait and a time interval equivalent to millisecondsTimeout
has passed.
Exceptions
The waitHandles
parameter is null
.
-or-
One or more of the objects in the waitHandles
array is null
.
The number of objects in waitHandles
is greater than the system permits.
waitHandles
is an array with no elements, and the .NET Framework version is 1.0 or 1.1.
millisecondsTimeout
is a negative number other than -1, which represents an infinite time-out.
The wait completed because a thread exited without releasing a mutex.
waitHandles
is an array with no elements, and the .NET Framework version is 2.0 or later.
The waitHandles
array contains a transparent proxy for a WaitHandle in another application domain.
Examples
The following code example demonstrates how to use the thread pool to simultaneously search for a file on multiple disks. For space considerations, only the root directory of each disk is searched.
using namespace System;
using namespace System::IO;
using namespace System::Threading;
ref class Search
{
private:
// Maintain state information to pass to FindCallback.
ref class State
{
public:
AutoResetEvent^ autoEvent;
String^ fileName;
State( AutoResetEvent^ autoEvent, String^ fileName )
: autoEvent( autoEvent ), fileName( fileName )
{}
};
public:
array<AutoResetEvent^>^autoEvents;
array<String^>^diskLetters;
// Search for stateInfo->fileName.
void FindCallback( Object^ state )
{
State^ stateInfo = dynamic_cast<State^>(state);
// Signal if the file is found.
if ( File::Exists( stateInfo->fileName ) )
{
stateInfo->autoEvent->Set();
}
}
Search()
{
// Retrieve an array of disk letters.
diskLetters = Environment::GetLogicalDrives();
autoEvents = gcnew array<AutoResetEvent^>(diskLetters->Length);
for ( int i = 0; i < diskLetters->Length; i++ )
{
autoEvents[ i ] = gcnew AutoResetEvent( false );
}
}
// Search for fileName in the root directory of all disks.
void FindFile( String^ fileName )
{
for ( int i = 0; i < diskLetters->Length; i++ )
{
Console::WriteLine( "Searching for {0} on {1}.", fileName, diskLetters[ i ] );
ThreadPool::QueueUserWorkItem( gcnew WaitCallback( this, &Search::FindCallback ), gcnew State( autoEvents[ i ],String::Concat( diskLetters[ i ], fileName ) ) );
}
// Wait for the first instance of the file to be found.
int index = WaitHandle::WaitAny( autoEvents, 3000, false );
if ( index == WaitHandle::WaitTimeout )
{
Console::WriteLine( "\n{0} not found.", fileName );
}
else
{
Console::WriteLine( "\n{0} found on {1}.", fileName, diskLetters[ index ] );
}
}
};
int main()
{
Search^ search = gcnew Search;
search->FindFile( "SomeFile.dat" );
}
using System;
using System.IO;
using System.Threading;
class Test
{
static void Main()
{
Search search = new Search();
search.FindFile("SomeFile.dat");
}
}
class Search
{
// Maintain state information to pass to FindCallback.
class State
{
public AutoResetEvent autoEvent;
public string fileName;
public State(AutoResetEvent autoEvent, string fileName)
{
this.autoEvent = autoEvent;
this.fileName = fileName;
}
}
AutoResetEvent[] autoEvents;
String[] diskLetters;
public Search()
{
// Retrieve an array of disk letters.
diskLetters = Environment.GetLogicalDrives();
autoEvents = new AutoResetEvent[diskLetters.Length];
for(int i = 0; i < diskLetters.Length; i++)
{
autoEvents[i] = new AutoResetEvent(false);
}
}
// Search for fileName in the root directory of all disks.
public void FindFile(string fileName)
{
for(int i = 0; i < diskLetters.Length; i++)
{
Console.WriteLine("Searching for {0} on {1}.",
fileName, diskLetters[i]);
ThreadPool.QueueUserWorkItem(
new WaitCallback(FindCallback),
new State(autoEvents[i], diskLetters[i] + fileName));
}
// Wait for the first instance of the file to be found.
int index = WaitHandle.WaitAny(autoEvents, 3000, false);
if(index == WaitHandle.WaitTimeout)
{
Console.WriteLine("\n{0} not found.", fileName);
}
else
{
Console.WriteLine("\n{0} found on {1}.", fileName,
diskLetters[index]);
}
}
// Search for stateInfo.fileName.
void FindCallback(object state)
{
State stateInfo = (State)state;
// Signal if the file is found.
if(File.Exists(stateInfo.fileName))
{
stateInfo.autoEvent.Set();
}
}
}
Imports System.IO
Imports System.Threading
Public Class Test
<MTAThread> _
Shared Sub Main()
Dim search As New Search()
search.FindFile("SomeFile.dat")
End Sub
End Class
Public Class Search
' Maintain state information to pass to FindCallback.
Class State
Public autoEvent As AutoResetEvent
Public fileName As String
Sub New(anEvent As AutoResetEvent, fName As String)
autoEvent = anEvent
fileName = fName
End Sub
End Class
Dim autoEvents() As AutoResetEvent
Dim diskLetters() As String
Sub New()
' Retrieve an array of disk letters.
diskLetters = Environment.GetLogicalDrives()
autoEvents = New AutoResetEvent(diskLetters.Length - 1) {}
For i As Integer = 0 To diskLetters.Length - 1
autoEvents(i) = New AutoResetEvent(False)
Next i
End Sub
' Search for fileName in the root directory of all disks.
Sub FindFile(fileName As String)
For i As Integer = 0 To diskLetters.Length - 1
Console.WriteLine("Searching for {0} on {1}.", _
fileName, diskLetters(i))
ThreadPool.QueueUserWorkItem(AddressOf FindCallback, _
New State(autoEvents(i), diskLetters(i) & fileName))
Next i
' Wait for the first instance of the file to be found.
Dim index As Integer = _
WaitHandle.WaitAny(autoEvents, 3000, False)
If index = WaitHandle.WaitTimeout
Console.WriteLine(vbCrLf & "{0} not found.", fileName)
Else
Console.WriteLine(vbCrLf & "{0} found on {1}.", _
fileName, diskLetters(index))
End If
End Sub
' Search for stateInfo.fileName.
Sub FindCallback(state As Object)
Dim stateInfo As State = DirectCast(state, State)
' Signal if the file is found.
If File.Exists(stateInfo.fileName) Then
stateInfo.autoEvent.Set()
End If
End Sub
End Class
Remarks
If millisecondsTimeout
is zero, the method does not block. It tests the state of the wait handles and returns immediately.
The WaitAny method throws an AbandonedMutexException only when the wait completes because of an abandoned mutex. If waitHandles
contains a released mutex with a lower index number than the abandoned mutex, the WaitAny method completes normally and the exception is not thrown. An abandoned mutex often indicates a serious coding error. In the case of a system-wide mutex, it might indicate that an application has been terminated abruptly (for example, by using Windows Task Manager). The exception contains information useful for debugging.
This method returns when the wait terminates, either when any of the handles are signaled or when a timeout occurs. If more than one object becomes signaled during the call, the return value is the array index of the signaled object with the smallest index value of all the signaled objects.
The maximum number of the wait handles is 64, and 63 if the current thread is in STA state.
Exiting the context
The exitContext
parameter has no effect unless this method is called from inside a nondefault managed context. The managed context can be nondefault if your thread is inside a call to an instance of a class derived from ContextBoundObject. Even if you're currently executing a method on a class that isn't derived from ContextBoundObject, like String, you can be in a nondefault context if a ContextBoundObject is on your stack in the current application domain.
When your code is executing in a nondefault context, specifying true
for exitContext
causes the thread to exit the nondefault managed context (that is, to transition to the default context) before executing this method. The thread returns to the original nondefault context after the call to this method completes.
Exiting the context can be useful when the context-bound class has the SynchronizationAttribute attribute. In that case, all calls to members of the class are automatically synchronized, and the synchronization domain is the entire body of code for the class. If code in the call stack of a member calls this method and specifies true
for exitContext
, the thread exits the synchronization domain, which allows a thread that's blocked on a call to any member of the object to proceed. When this method returns, the thread that made the call must wait to reenter the synchronization domain.
Applies to
WaitAny(WaitHandle[], TimeSpan, Boolean)
- Source:
- WaitHandle.cs
- Source:
- WaitHandle.cs
- Source:
- WaitHandle.cs
Waits for any of the elements in the specified array to receive a signal, using a TimeSpan to specify the time interval and specifying whether to exit the synchronization domain before the wait.
public:
static int WaitAny(cli::array <System::Threading::WaitHandle ^> ^ waitHandles, TimeSpan timeout, bool exitContext);
public static int WaitAny (System.Threading.WaitHandle[] waitHandles, TimeSpan timeout, bool exitContext);
static member WaitAny : System.Threading.WaitHandle[] * TimeSpan * bool -> int
Public Shared Function WaitAny (waitHandles As WaitHandle(), timeout As TimeSpan, exitContext As Boolean) As Integer
Parameters
- waitHandles
- WaitHandle[]
A WaitHandle
array containing the objects for which the current instance will wait.
- timeout
- TimeSpan
A TimeSpan that represents the number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely.
- exitContext
- Boolean
true
to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it afterward; otherwise, false
.
Returns
The array index of the object that satisfied the wait, or WaitTimeout if no object satisfied the wait and a time interval equivalent to timeout
has passed.
Exceptions
The waitHandles
parameter is null
.
-or-
One or more of the objects in the waitHandles
array is null
.
The number of objects in waitHandles
is greater than the system permits.
waitHandles
is an array with no elements, and the .NET Framework version is 1.0 or 1.1.
timeout
is a negative number other than -1 milliseconds, which represents an infinite time-out.
-or-
timeout
is greater than Int32.MaxValue.
The wait completed because a thread exited without releasing a mutex.
waitHandles
is an array with no elements, and the .NET Framework version is 2.0 or later.
The waitHandles
array contains a transparent proxy for a WaitHandle in another application domain.
Examples
The following code example demonstrates how to use the thread pool to simultaneously search for a file on multiple disks. For space considerations, only the root directory of each disk is searched.
using namespace System;
using namespace System::IO;
using namespace System::Threading;
ref class Search
{
private:
// Maintain state information to pass to FindCallback.
ref class State
{
public:
AutoResetEvent^ autoEvent;
String^ fileName;
State( AutoResetEvent^ autoEvent, String^ fileName )
: autoEvent( autoEvent ), fileName( fileName )
{}
};
public:
array<AutoResetEvent^>^autoEvents;
array<String^>^diskLetters;
// Search for stateInfo->fileName.
void FindCallback( Object^ state )
{
State^ stateInfo = dynamic_cast<State^>(state);
// Signal if the file is found.
if ( File::Exists( stateInfo->fileName ) )
{
stateInfo->autoEvent->Set();
}
}
Search()
{
// Retrieve an array of disk letters.
diskLetters = Environment::GetLogicalDrives();
autoEvents = gcnew array<AutoResetEvent^>(diskLetters->Length);
for ( int i = 0; i < diskLetters->Length; i++ )
{
autoEvents[ i ] = gcnew AutoResetEvent( false );
}
}
// Search for fileName in the root directory of all disks.
void FindFile( String^ fileName )
{
for ( int i = 0; i < diskLetters->Length; i++ )
{
Console::WriteLine( "Searching for {0} on {1}.", fileName, diskLetters[ i ] );
ThreadPool::QueueUserWorkItem( gcnew WaitCallback( this, &Search::FindCallback ), gcnew State( autoEvents[ i ],String::Concat( diskLetters[ i ], fileName ) ) );
}
// Wait for the first instance of the file to be found.
int index = WaitHandle::WaitAny( autoEvents, TimeSpan(0,0,3), false );
if ( index == WaitHandle::WaitTimeout )
{
Console::WriteLine( "\n{0} not found.", fileName );
}
else
{
Console::WriteLine( "\n{0} found on {1}.", fileName, diskLetters[ index ] );
}
}
};
int main()
{
Search^ search = gcnew Search;
search->FindFile( "SomeFile.dat" );
}
using System;
using System.IO;
using System.Threading;
class Test
{
static void Main()
{
Search search = new Search();
search.FindFile("SomeFile.dat");
}
}
class Search
{
// Maintain state information to pass to FindCallback.
class State
{
public AutoResetEvent autoEvent;
public string fileName;
public State(AutoResetEvent autoEvent, string fileName)
{
this.autoEvent = autoEvent;
this.fileName = fileName;
}
}
AutoResetEvent[] autoEvents;
String[] diskLetters;
public Search()
{
// Retrieve an array of disk letters.
diskLetters = Environment.GetLogicalDrives();
autoEvents = new AutoResetEvent[diskLetters.Length];
for(int i = 0; i < diskLetters.Length; i++)
{
autoEvents[i] = new AutoResetEvent(false);
}
}
// Search for fileName in the root directory of all disks.
public void FindFile(string fileName)
{
for(int i = 0; i < diskLetters.Length; i++)
{
Console.WriteLine("Searching for {0} on {1}.",
fileName, diskLetters[i]);
ThreadPool.QueueUserWorkItem(
new WaitCallback(FindCallback),
new State(autoEvents[i], diskLetters[i] + fileName));
}
// Wait for the first instance of the file to be found.
int index = WaitHandle.WaitAny(
autoEvents, new TimeSpan(0, 0, 3), false);
if(index == WaitHandle.WaitTimeout)
{
Console.WriteLine("\n{0} not found.", fileName);
}
else
{
Console.WriteLine("\n{0} found on {1}.", fileName,
diskLetters[index]);
}
}
// Search for stateInfo.fileName.
void FindCallback(object state)
{
State stateInfo = (State)state;
// Signal if the file is found.
if(File.Exists(stateInfo.fileName))
{
stateInfo.autoEvent.Set();
}
}
}
Imports System.IO
Imports System.Threading
Public Class Test
<MTAThread> _
Shared Sub Main()
Dim search As New Search()
search.FindFile("SomeFile.dat")
End Sub
End Class
Public Class Search
' Maintain state information to pass to FindCallback.
Class State
Public autoEvent As AutoResetEvent
Public fileName As String
Sub New(anEvent As AutoResetEvent, fName As String)
autoEvent = anEvent
fileName = fName
End Sub
End Class
Dim autoEvents() As AutoResetEvent
Dim diskLetters() As String
Sub New()
' Retrieve an array of disk letters.
diskLetters = Environment.GetLogicalDrives()
autoEvents = New AutoResetEvent(diskLetters.Length - 1) {}
For i As Integer = 0 To diskLetters.Length - 1
autoEvents(i) = New AutoResetEvent(False)
Next i
End Sub
' Search for fileName in the root directory of all disks.
Sub FindFile(fileName As String)
For i As Integer = 0 To diskLetters.Length - 1
Console.WriteLine("Searching for {0} on {1}.", _
fileName, diskLetters(i))
ThreadPool.QueueUserWorkItem(AddressOf FindCallback, _
New State(autoEvents(i), diskLetters(i) & fileName))
Next i
' Wait for the first instance of the file to be found.
Dim index As Integer = WaitHandle.WaitAny( _
autoEvents, New TimeSpan(0, 0, 3), False)
If index = WaitHandle.WaitTimeout
Console.WriteLine(vbCrLf & "{0} not found.", fileName)
Else
Console.WriteLine(vbCrLf & "{0} found on {1}.", _
fileName, diskLetters(index))
End If
End Sub
' Search for stateInfo.fileName.
Sub FindCallback(state As Object)
Dim stateInfo As State = DirectCast(state, State)
' Signal if the file is found.
If File.Exists(stateInfo.fileName) Then
stateInfo.autoEvent.Set()
End If
End Sub
End Class
Remarks
If timeout
is zero, the method does not block. It tests the state of the wait handles and returns immediately.
The WaitAny method throws an AbandonedMutexException only when the wait completes because of an abandoned mutex. If waitHandles
contains a released mutex with a lower index number than the abandoned mutex, the WaitAny method completes normally and the exception is not thrown. An abandoned mutex often indicates a serious coding error. In the case of a system-wide mutex, it might indicate that an application has been terminated abruptly (for example, by using Windows Task Manager). The exception contains information useful for debugging.
This method returns when the wait terminates, either when any of the handles are signaled or when a time-out occurs. If more than one object becomes signaled during the call, the return value is the array index of the signaled object with the smallest index value of all the signaled objects.
The maximum number of the wait handles is 64, and 63 if the current thread is in STA state.
The maximum value for timeout
is Int32.MaxValue.
Exiting the context
The exitContext
parameter has no effect unless this method is called from inside a nondefault managed context. The managed context can be nondefault if your thread is inside a call to an instance of a class derived from ContextBoundObject. Even if you're currently executing a method on a class that isn't derived from ContextBoundObject, like String, you can be in a nondefault context if a ContextBoundObject is on your stack in the current application domain.
When your code is executing in a nondefault context, specifying true
for exitContext
causes the thread to exit the nondefault managed context (that is, to transition to the default context) before executing this method. The thread returns to the original nondefault context after the call to this method completes.
Exiting the context can be useful when the context-bound class has the SynchronizationAttribute attribute. In that case, all calls to members of the class are automatically synchronized, and the synchronization domain is the entire body of code for the class. If code in the call stack of a member calls this method and specifies true
for exitContext
, the thread exits the synchronization domain, which allows a thread that's blocked on a call to any member of the object to proceed. When this method returns, the thread that made the call must wait to reenter the synchronization domain.