WaitHandle.WaitAny Método
Definición
Importante
Parte de la información hace referencia a la versión preliminar del producto, que puede haberse modificado sustancialmente antes de lanzar la versión definitiva. Microsoft no otorga ninguna garantía, explícita o implícita, con respecto a la información proporcionada aquí.
Espera a que cualquiera de los elementos de la matriz especificada reciba una señal.
Sobrecargas
| Nombre | Description |
|---|---|
| WaitAny(WaitHandle[]) |
Espera a que cualquiera de los elementos de la matriz especificada reciba una señal. |
| WaitAny(WaitHandle[], Int32) |
Espera a que cualquiera de los elementos de la matriz especificada reciba una señal, utilizando un entero de 32 bits con signo para especificar el intervalo de tiempo. |
| WaitAny(WaitHandle[], TimeSpan) |
Espera a que cualquiera de los elementos de la matriz especificada reciba una señal, utilizando para TimeSpan especificar el intervalo de tiempo. |
| WaitAny(WaitHandle[], Int32, Boolean) |
Espera a que cualquiera de los elementos de la matriz especificada reciba una señal, utilizando un entero de 32 bits con signo para especificar el intervalo de tiempo y especificando si se sale del dominio de sincronización antes de la espera. |
| WaitAny(WaitHandle[], TimeSpan, Boolean) |
Espera a que cualquiera de los elementos de la matriz especificada reciba una señal, utilizando para TimeSpan especificar el intervalo de tiempo y especificando si se sale del dominio de sincronización antes de la espera. |
WaitAny(WaitHandle[])
Espera a que cualquiera de los elementos de la matriz especificada reciba una señal.
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
Parámetros
- waitHandles
- WaitHandle[]
Matriz WaitHandle que contiene los objetos para los que esperará la instancia actual.
Devoluciones
Índice de matriz del objeto que cumplió la espera.
Excepciones
El waitHandles parámetro es null.
O bien
Uno o varios de los objetos de la waitHandles matriz son null.
El número de objetos de waitHandles es mayor que el sistema permite.
waitHandles es una matriz sin elementos y la versión de .NET Framework es 1.0 o 1.1.
La espera se completó porque un subproceso salió sin liberar una exclusión mutua.
waitHandles es una matriz sin elementos y la versión de .NET Framework es 2.0 o posterior.
La waitHandles matriz contiene un proxy transparente para en WaitHandle otro dominio de aplicación.
Ejemplos
En el ejemplo de código siguiente se muestra cómo llamar al WaitAny método .
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).
Comentarios
AbandonedMutexException es nuevo en la versión 2.0 de .NET Framework. En versiones anteriores, el WaitAny método devuelve true si se completa la espera porque se abandona una exclusión mutua. Una exclusión mutua abandonada suele indicar un error de codificación grave. En el caso de una exclusión mutua en todo el sistema, podría indicar que una aplicación se ha terminado abruptamente (por ejemplo, mediante el Administrador de tareas de Windows). La excepción contiene información útil para la depuración.
El WaitAny método produce un AbandonedMutexException solo cuando se completa la espera debido a una exclusión mutua abandonada. Si waitHandles contiene una exclusión mutua liberado con un número de índice menor que la exclusión mutua abandonada, el WaitAny método se completa normalmente y la excepción no se produce.
Note
En versiones de .NET Framework anteriores a la versión 2.0, si un subproceso sale o anula sin liberar explícitamente un Mutex y que Mutex está en el índice 0 (cero) en una matriz de WaitAny en otro subproceso, el índice devuelto por WaitAny es 128 en lugar de 0.
Este método devuelve cuando se señala cualquier identificador. Si se señala más de un objeto durante la llamada, el valor devuelto es el índice de matriz del objeto señalado con el valor de índice más pequeño de todos los objetos señalados.
El número máximo de identificadores de espera es 64 y 63 si el subproceso actual está en STA estado.
Llamar a esta sobrecarga de método es equivalente a llamar a la sobrecarga del WaitAny(WaitHandle[], Int32, Boolean) método y especificar -1 (o Timeout.Infinite) para millisecondsTimeout y true para exitContext.
Se aplica a
WaitAny(WaitHandle[], Int32)
Espera a que cualquiera de los elementos de la matriz especificada reciba una señal, utilizando un entero de 32 bits con signo para especificar el intervalo de tiempo.
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
Parámetros
- waitHandles
- WaitHandle[]
Matriz WaitHandle que contiene los objetos para los que esperará la instancia actual.
- millisecondsTimeout
- Int32
Número de milisegundos que se van a esperar o Infinite (-1) para esperar indefinidamente.
Devoluciones
Índice de matriz del objeto que cumplió la espera, o WaitTimeout si ningún objeto cumplió la espera y un intervalo de tiempo equivalente a millisecondsTimeout ha pasado.
Excepciones
El waitHandles parámetro es null.
O bien
Uno o varios de los objetos de la waitHandles matriz son null.
El número de objetos de waitHandles es mayor que el sistema permite.
millisecondsTimeout es un número negativo distinto de -1, que representa un tiempo de espera infinito.
La espera se completó porque un subproceso salió sin liberar una exclusión mutua.
waitHandles es una matriz sin elementos.
La waitHandles matriz contiene un proxy transparente para en WaitHandle otro dominio de aplicación.
Comentarios
Si millisecondsTimeout es cero, el método no se bloquea. Comprueba el estado de los identificadores de espera y devuelve inmediatamente.
El WaitAny método produce un AbandonedMutexException solo cuando se completa la espera debido a una exclusión mutua abandonada. Si waitHandles contiene una exclusión mutua liberado con un número de índice menor que la exclusión mutua abandonada, el WaitAny método se completa normalmente y la excepción no se produce.
Este método devuelve cuando finaliza la espera, ya sea cuando se señala cualquiera de los identificadores o cuando se produce un tiempo de espera. Si se señala más de un objeto durante la llamada, el valor devuelto es el índice de matriz del objeto señalado con el valor de índice más pequeño de todos los objetos señalados.
El número máximo de identificadores de espera es 64 y 63 si el subproceso actual está en STA estado.
Llamar a esta sobrecarga de método es la misma que llamar a la WaitAny(WaitHandle[], Int32, Boolean) sobrecarga y especificar false para exitContext.
Se aplica a
WaitAny(WaitHandle[], TimeSpan)
Espera a que cualquiera de los elementos de la matriz especificada reciba una señal, utilizando para TimeSpan especificar el intervalo de tiempo.
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
Parámetros
- waitHandles
- WaitHandle[]
Matriz WaitHandle que contiene los objetos para los que esperará la instancia actual.
- timeout
- TimeSpan
TimeSpan que representa el número de milisegundos que se van a esperar, o que TimeSpan representa -1 milisegundos que se van a esperar indefinidamente.
Devoluciones
Índice de matriz del objeto que cumplió la espera, o WaitTimeout si ningún objeto cumplió la espera y un intervalo de tiempo equivalente a timeout ha pasado.
Excepciones
El waitHandles parámetro es null.
O bien
Uno o varios de los objetos de la waitHandles matriz son null.
El número de objetos de waitHandles es mayor que el sistema permite.
timeout es un número negativo distinto de -1 milisegundos, que representa un tiempo de espera infinito.
O bien
timeout es mayor que Int32.MaxValue.
La espera se completó porque un subproceso salió sin liberar una exclusión mutua.
waitHandles es una matriz sin elementos.
La waitHandles matriz contiene un proxy transparente para en WaitHandle otro dominio de aplicación.
Comentarios
Si timeout es cero, el método no se bloquea. Comprueba el estado de los identificadores de espera y devuelve inmediatamente.
El WaitAny método produce un AbandonedMutexException solo cuando se completa la espera debido a una exclusión mutua abandonada. Si waitHandles contiene una exclusión mutua liberado con un número de índice menor que la exclusión mutua abandonada, el WaitAny método se completa normalmente y la excepción no se produce.
Este método devuelve cuando finaliza la espera, ya sea cuando se señala cualquiera de los identificadores o cuando se produce un tiempo de espera. Si se señala más de un objeto durante la llamada, el valor devuelto es el índice de matriz del objeto señalado con el valor de índice más pequeño de todos los objetos señalados.
El número máximo de identificadores de espera es 64 y 63 si el subproceso actual está en STA estado.
El valor máximo de timeout es Int32.MaxValue.
Llamar a esta sobrecarga de método es la misma que llamar a la WaitAny(WaitHandle[], TimeSpan, Boolean) sobrecarga y especificar false para exitContext.
Se aplica a
WaitAny(WaitHandle[], Int32, Boolean)
Espera a que cualquiera de los elementos de la matriz especificada reciba una señal, utilizando un entero de 32 bits con signo para especificar el intervalo de tiempo y especificando si se sale del dominio de sincronización antes de la espera.
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
Parámetros
- waitHandles
- WaitHandle[]
Matriz WaitHandle que contiene los objetos para los que esperará la instancia actual.
- millisecondsTimeout
- Int32
Número de milisegundos que se van a esperar o Infinite (-1) para esperar indefinidamente.
- exitContext
- Boolean
true para salir del dominio de sincronización del contexto antes de la espera (si está en un contexto sincronizado) y volver a adquirirlo después; de lo contrario, false.
Devoluciones
Índice de matriz del objeto que cumplió la espera, o WaitTimeout si ningún objeto cumplió la espera y un intervalo de tiempo equivalente a millisecondsTimeout ha pasado.
Excepciones
El waitHandles parámetro es null.
O bien
Uno o varios de los objetos de la waitHandles matriz son null.
El número de objetos de waitHandles es mayor que el sistema permite.
waitHandles es una matriz sin elementos y la versión de .NET Framework es 1.0 o 1.1.
millisecondsTimeout es un número negativo distinto de -1, que representa un tiempo de espera infinito.
La espera se completó porque un subproceso salió sin liberar una exclusión mutua.
waitHandles es una matriz sin elementos y la versión de .NET Framework es 2.0 o posterior.
La waitHandles matriz contiene un proxy transparente para en WaitHandle otro dominio de aplicación.
Ejemplos
En el ejemplo de código siguiente se muestra cómo usar el grupo de subprocesos para buscar simultáneamente un archivo en varios discos. En el caso de las consideraciones de espacio, solo se busca el directorio raíz de cada disco.
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
Comentarios
Si millisecondsTimeout es cero, el método no se bloquea. Comprueba el estado de los identificadores de espera y devuelve inmediatamente.
El WaitAny método produce un AbandonedMutexException solo cuando se completa la espera debido a una exclusión mutua abandonada. Si waitHandles contiene una exclusión mutua liberado con un número de índice menor que la exclusión mutua abandonada, el WaitAny método se completa normalmente y la excepción no se produce. Una exclusión mutua abandonada suele indicar un error de codificación grave. En el caso de una exclusión mutua en todo el sistema, podría indicar que una aplicación se ha terminado abruptamente (por ejemplo, mediante el Administrador de tareas de Windows). La excepción contiene información útil para la depuración.
Este método devuelve cuando finaliza la espera, ya sea cuando se señala cualquiera de los identificadores o cuando se produce un tiempo de espera. Si se señala más de un objeto durante la llamada, el valor devuelto es el índice de matriz del objeto señalado con el valor de índice más pequeño de todos los objetos señalados.
El número máximo de identificadores de espera es 64 y 63 si el subproceso actual está en STA estado.
Salir del contexto
El exitContext parámetro no tiene ningún efecto a menos que se llame a este método desde dentro de un contexto administrado no predeterminado. El contexto administrado puede no ser predeterminado si el subproceso está dentro de una llamada a una instancia de una clase derivada de ContextBoundObject. Incluso si actualmente está ejecutando un método en una clase que no se deriva de ContextBoundObject, como String, puede estar en un contexto no predeterminado si se ContextBoundObject encuentra en la pila en el dominio de aplicación actual.
Cuando el código se ejecuta en un contexto no predeterminado, especificar true para exitContext hace que el subproceso salga del contexto administrado no predeterminado (es decir, para realizar la transición al contexto predeterminado) antes de ejecutar este método. El subproceso vuelve al contexto no predeterminado original una vez completada la llamada a este método.
Salir del contexto puede ser útil cuando la clase enlazada al contexto tiene el SynchronizationAttribute atributo . En ese caso, todas las llamadas a los miembros de la clase se sincronizan automáticamente y el dominio de sincronización es todo el cuerpo de código de la clase. Si el código de la pila de llamadas de un miembro llama a este método y especifica para true, el subproceso exitContext sale del dominio de sincronización, lo que permite que un subproceso bloqueado en una llamada a cualquier miembro del objeto continúe. Cuando este método vuelve, el subproceso que realizó la llamada debe esperar a volver a escribir el dominio de sincronización.
Se aplica a
WaitAny(WaitHandle[], TimeSpan, Boolean)
Espera a que cualquiera de los elementos de la matriz especificada reciba una señal, utilizando para TimeSpan especificar el intervalo de tiempo y especificando si se sale del dominio de sincronización antes de la espera.
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
Parámetros
- waitHandles
- WaitHandle[]
Matriz WaitHandle que contiene los objetos para los que esperará la instancia actual.
- timeout
- TimeSpan
TimeSpan que representa el número de milisegundos que se van a esperar, o que TimeSpan representa -1 milisegundos que se van a esperar indefinidamente.
- exitContext
- Boolean
true para salir del dominio de sincronización del contexto antes de la espera (si está en un contexto sincronizado) y volver a adquirirlo después; de lo contrario, false.
Devoluciones
Índice de matriz del objeto que cumplió la espera, o WaitTimeout si ningún objeto cumplió la espera y un intervalo de tiempo equivalente a timeout ha pasado.
Excepciones
El waitHandles parámetro es null.
O bien
Uno o varios de los objetos de la waitHandles matriz son null.
El número de objetos de waitHandles es mayor que el sistema permite.
waitHandles es una matriz sin elementos y la versión de .NET Framework es 1.0 o 1.1.
timeout es un número negativo distinto de -1 milisegundos, que representa un tiempo de espera infinito.
O bien
timeout es mayor que Int32.MaxValue.
La espera se completó porque un subproceso salió sin liberar una exclusión mutua.
waitHandles es una matriz sin elementos y la versión de .NET Framework es 2.0 o posterior.
La waitHandles matriz contiene un proxy transparente para en WaitHandle otro dominio de aplicación.
Ejemplos
En el ejemplo de código siguiente se muestra cómo usar el grupo de subprocesos para buscar simultáneamente un archivo en varios discos. En el caso de las consideraciones de espacio, solo se busca el directorio raíz de cada disco.
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
Comentarios
Si timeout es cero, el método no se bloquea. Comprueba el estado de los identificadores de espera y devuelve inmediatamente.
El WaitAny método produce un AbandonedMutexException solo cuando se completa la espera debido a una exclusión mutua abandonada. Si waitHandles contiene una exclusión mutua liberado con un número de índice menor que la exclusión mutua abandonada, el WaitAny método se completa normalmente y la excepción no se produce. Una exclusión mutua abandonada suele indicar un error de codificación grave. En el caso de una exclusión mutua en todo el sistema, podría indicar que una aplicación se ha terminado abruptamente (por ejemplo, mediante el Administrador de tareas de Windows). La excepción contiene información útil para la depuración.
Este método devuelve cuando finaliza la espera, ya sea cuando se señala cualquiera de los identificadores o cuando se produce un tiempo de espera. Si se señala más de un objeto durante la llamada, el valor devuelto es el índice de matriz del objeto señalado con el valor de índice más pequeño de todos los objetos señalados.
El número máximo de identificadores de espera es 64 y 63 si el subproceso actual está en STA estado.
El valor máximo de timeout es Int32.MaxValue.
Salir del contexto
El exitContext parámetro no tiene ningún efecto a menos que se llame a este método desde dentro de un contexto administrado no predeterminado. El contexto administrado puede no ser predeterminado si el subproceso está dentro de una llamada a una instancia de una clase derivada de ContextBoundObject. Incluso si actualmente está ejecutando un método en una clase que no se deriva de ContextBoundObject, como String, puede estar en un contexto no predeterminado si se ContextBoundObject encuentra en la pila en el dominio de aplicación actual.
Cuando el código se ejecuta en un contexto no predeterminado, especificar true para exitContext hace que el subproceso salga del contexto administrado no predeterminado (es decir, para realizar la transición al contexto predeterminado) antes de ejecutar este método. El subproceso vuelve al contexto no predeterminado original una vez completada la llamada a este método.
Salir del contexto puede ser útil cuando la clase enlazada al contexto tiene el SynchronizationAttribute atributo . En ese caso, todas las llamadas a los miembros de la clase se sincronizan automáticamente y el dominio de sincronización es todo el cuerpo de código de la clase. Si el código de la pila de llamadas de un miembro llama a este método y especifica para true, el subproceso exitContext sale del dominio de sincronización, lo que permite que un subproceso bloqueado en una llamada a cualquier miembro del objeto continúe. Cuando este método vuelve, el subproceso que realizó la llamada debe esperar a volver a escribir el dominio de sincronización.