WaitHandle.WaitAny Método

Definición

Espera a que cualquiera de los elementos de la matriz especificada reciba una señal.

Sobrecargas

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, usando un TimeSpan para especificar el intervalo de tiempo.

WaitAny(WaitHandle[], Int32, Boolean)

Espera a que cualquiera de los elementos de la matriz especificada reciba una señal; utiliza un entero de 32 bits con signo para determinar el intervalo de tiempo y especifica si se va a salir 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; usa un TimeSpan para especificar el intervalo de tiempo y especifica si se va a salir 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 por los que la instancia actual esperará.

Devoluciones

Int32

Índice de la matriz del objeto que satisfizo la espera.

Excepciones

El parámetro waitHandles es null.

o bien Uno o varios objetos de la matriz waitHandles son null.

El número de objetos de waitHandles es mayor de lo que permite el sistema.

waitHandles es una matriz sin elementos y la versión de .NET Framework es 1.0 o 1.1.

La espera finalizó porque un subproceso se cierra 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 matriz waitHandles contiene un proxy transparente para un WaitHandle en otro dominio de aplicación.

Ejemplos

En el ejemplo de código siguiente se muestra cómo llamar al WaitAny método .

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 tasks are 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

AbandonedMutexExceptiones una novedad de la .NET Framework versión 2.0. En versiones anteriores, el método devuelve si la espera se completa porque se abandona WaitAny true 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 de todo el sistema, podría indicar que una aplicación se ha terminado repentinamente (por ejemplo, mediante Windows Administrador de tareas). La excepción contiene información útil para la depuración.

El WaitAny método produce un solo cuando la espera se completa debido a una AbandonedMutexException exclusión mutua abandonada. Si contiene una exclusión mutua liberada con un número de índice inferior al de la exclusión mutua abandonada, el método se completa normalmente y no se waitHandles WaitAny produce la excepción.

Nota

En las versiones del .NET Framework anteriores a la versión 2.0, si un subproceso se cierra o anula sin liberar explícitamente un , y que se encuentra en el índice 0 (cero) de una matriz en otro subproceso, el índice devuelto por es 128 en lugar Mutex Mutex de WaitAny WaitAny 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 equivale a llamar a la sobrecarga del método y especificar WaitAny(WaitHandle[], Int32, Boolean) -1 (o Timeout.Infinite ) para y para millisecondsTimeout true 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 por los que la instancia actual esperará.

millisecondsTimeout
Int32

Número de milisegundos de espera o Infinite (-1) para esperar indefinidamente.

Devoluciones

Int32

Índice de matriz del objeto que satisfizo la espera o WaitTimeout si ningún objeto satisfizo la espera y transcurrió un intervalo de tiempo equivalente a millisecondsTimeout.

Excepciones

El parámetro waitHandles es null.

o bien Uno o varios objetos de la matriz waitHandles son null.

El número de objetos de waitHandles es mayor de lo que permite el sistema.

millisecondsTimeout es un número negativo distinto de-1, que representa un tiempo de espera infinito.

La espera finalizó porque un subproceso se cierra sin liberar una exclusión mutua.

waitHandles es una matriz sin elementos.

La matriz waitHandles contiene un proxy transparente para un WaitHandle en 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 solo cuando la espera se completa debido a una AbandonedMutexException exclusión mutua abandonada. Si contiene una exclusión mutua liberada con un número de índice inferior al de la exclusión mutua abandonada, el método se completa normalmente y no se waitHandles WaitAny produce la excepción.

Este método devuelve cuando finaliza la espera, ya sea cuando se señala cualquiera de los identificadores o cuando se agota el 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 lo mismo que llamar a la WaitAny(WaitHandle[], Int32, Boolean) sobrecarga y especificar para false exitContext .

Se aplica a

WaitAny(WaitHandle[], TimeSpan)

Espera a que cualquiera de los elementos de la matriz especificada reciba una señal, usando un TimeSpan para 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 por los que la instancia actual esperará.

timeout
TimeSpan

Estructura TimeSpan que representa el número de milisegundos de espera o estructura TimeSpan que representa -1 milisegundos para esperar indefinidamente.

Devoluciones

Int32

Índice de matriz del objeto que satisfizo la espera o WaitTimeout si ningún objeto satisfizo la espera y transcurrió un intervalo de tiempo equivalente a timeout.

Excepciones

El parámetro waitHandles es null.

o bien Uno o varios objetos de la matriz waitHandles son null.

El número de objetos de waitHandles es mayor de lo que permite el sistema.

timeout es un número negativo distinto de -1 milisegundos, que representa un tiempo de espera infinito. O bien timeout es mayor que MaxValue.

La espera finalizó porque un subproceso se cierra sin liberar una exclusión mutua.

waitHandles es una matriz sin elementos.

La matriz waitHandles contiene un proxy transparente para un WaitHandle en 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 solo cuando la espera se completa debido a una AbandonedMutexException exclusión mutua abandonada. Si contiene una exclusión mutua liberada con un número de índice inferior al de la exclusión mutua abandonada, el método se completa normalmente y no se waitHandles WaitAny produce la excepció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 .

Llamar a esta sobrecarga de método es lo mismo que llamar a la WaitAny(WaitHandle[], TimeSpan, Boolean) sobrecarga y especificar para false exitContext .

Se aplica a

WaitAny(WaitHandle[], Int32, Boolean)

Espera a que cualquiera de los elementos de la matriz especificada reciba una señal; utiliza un entero de 32 bits con signo para determinar el intervalo de tiempo y especifica si se va a salir 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 por los que la instancia actual esperará.

millisecondsTimeout
Int32

Número de milisegundos de espera o Infinite (-1) para esperar indefinidamente.

exitContext
Boolean

true para salir del dominio de sincronización del contexto antes de la espera (en caso de encontrarse en un contexto sincronizado) y volver a adquirirlo más tarde; de lo contrario, false.

Devoluciones

Int32

Índice de matriz del objeto que satisfizo la espera o WaitTimeout si ningún objeto satisfizo la espera y transcurrió un intervalo de tiempo equivalente a millisecondsTimeout.

Excepciones

El parámetro waitHandles es null.

o bien Uno o varios objetos de la matriz waitHandles son null.

El número de objetos de waitHandles es mayor de lo que permite el sistema.

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 finalizó porque un subproceso se cierra 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 matriz waitHandles contiene un proxy transparente para un WaitHandle en 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. Para las consideraciones de espacio, solo se busca en el directorio raíz de cada disco.

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

Comentarios

Si millisecondsTimeout es cero, el método no se bloquea. Comprueba el estado de los identificadores de espera y devuelve inmediatamente.

AbandonedMutexExceptiones una novedad de .NET Framework versión 2.0. En versiones anteriores, el método devuelve si la espera se completa porque se abandona WaitAny true 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 de todo el sistema, podría indicar que una aplicación se ha terminado repentinamente (por ejemplo, mediante Windows Administrador de tareas). La excepción contiene información útil para la depuración.

El WaitAny método produce un solo cuando la espera se completa debido a una AbandonedMutexException exclusión mutua abandonada. Si contiene una exclusión mutua liberada con un número de índice inferior al de la exclusión mutua abandonada, el método se completa normalmente y no se waitHandles WaitAny produce la excepción.

Nota

En las versiones del .NET Framework anteriores a la versión 2.0, si un subproceso se cierra o anula sin liberar explícitamente un , y que se encuentra en el índice 0 (cero) de una matriz en otro subproceso, el índice devuelto por es 128 en lugar Mutex Mutex de WaitAny WaitAny 0.

Este método devuelve cuando finaliza la espera, ya sea cuando se señala cualquiera de los identificadores o cuando se agota el 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 .

Notas sobre la salida del contexto

El exitContext parámetro no tiene ningún efecto a menos que se llame al método desde dentro de un contexto administrado WaitAny no predeterminado. Esto puede ocurrir 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 deriva de , como , puede estar en un contexto no predeterminado si está en la pila en el dominio de ContextBoundObject String aplicación ContextBoundObject actual.

Cuando el código se ejecuta en un contexto no predeterminado, la especificación de para hace que el subproceso salga del contexto administrado no predeterminado (es decir, para realizar la transición al contexto predeterminado) antes de ejecutar true exitContext el método WaitAny . El subproceso vuelve al contexto original no predeterminado una vez completada la llamada WaitAny al método .

Esto puede ser útil cuando la clase enlazada al contexto tiene SynchronizationAttribute . En ese caso, todas las llamadas a los miembros de la clase se sincronizan automáticamente y el dominio de sincronización es el cuerpo completo del código de la clase. Si el código de la pila de llamadas de un miembro llama al método y especifica para , el subproceso sale del dominio de sincronización, lo que permite que un subproceso bloqueado en una llamada a cualquier miembro del objeto WaitAny true exitContext continúe. Cuando el WaitAny método vuelve, el subproceso que realizó la llamada debe esperar para 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; usa un TimeSpan para especificar el intervalo de tiempo y especifica si se va a salir 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 por los que la instancia actual esperará.

timeout
TimeSpan

Estructura TimeSpan que representa el número de milisegundos de espera o estructura TimeSpan que representa -1 milisegundos para esperar indefinidamente.

exitContext
Boolean

true para salir del dominio de sincronización del contexto antes de la espera (en caso de encontrarse en un contexto sincronizado) y volver a adquirirlo más tarde; de lo contrario, false.

Devoluciones

Int32

Índice de matriz del objeto que satisfizo la espera o WaitTimeout si ningún objeto satisfizo la espera y transcurrió un intervalo de tiempo equivalente a timeout.

Excepciones

El parámetro waitHandles es null.

o bien Uno o varios objetos de la matriz waitHandles son null.

El número de objetos de waitHandles es mayor de lo que permite el sistema.

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 MaxValue.

La espera finalizó porque un subproceso se cierra 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 matriz waitHandles contiene un proxy transparente para un WaitHandle en 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. Para las consideraciones de espacio, solo se busca en el directorio raíz de cada disco.

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

Comentarios

Si timeout es cero, el método no se bloquea. Comprueba el estado de los identificadores de espera y devuelve inmediatamente.

AbandonedMutexExceptiones una novedad de .NET Framework versión 2.0. En versiones anteriores, el método devuelve si la espera se completa porque se abandona WaitAny true 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 de todo el sistema, podría indicar que una aplicación se ha terminado repentinamente (por ejemplo, mediante Windows Administrador de tareas). La excepción contiene información útil para la depuración.

El WaitAny método produce un solo cuando la espera se completa debido a una AbandonedMutexException exclusión mutua abandonada. Si contiene una exclusión mutua liberada con un número de índice inferior al de la exclusión mutua abandonada, el método se completa normalmente y no se waitHandles WaitAny produce la excepción.

Nota

En las versiones del .NET Framework anteriores a la versión 2.0, si un subproceso se cierra o anula sin liberar explícitamente un , y que se encuentra en el índice 0 (cero) de una matriz en otro subproceso, el índice devuelto por es 128 en lugar Mutex Mutex de WaitAny WaitAny 0.

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 .

Notas sobre la salida del contexto

El exitContext parámetro no tiene ningún efecto a menos que se llame al método desde dentro de un contexto administrado WaitAny no predeterminado. Esto puede ocurrir 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 deriva de , como , puede estar en un contexto no predeterminado si está en la pila en el dominio de ContextBoundObject String aplicación ContextBoundObject actual.

Cuando el código se ejecuta en un contexto no predeterminado, la especificación de para hace que el subproceso salga del contexto administrado no predeterminado (es decir, para realizar la transición al contexto predeterminado) antes de ejecutar true exitContext el método WaitAny . El subproceso vuelve al contexto original no predeterminado una vez completada la llamada WaitAny al método .

Esto puede ser útil cuando la clase enlazada al contexto tiene SynchronizationAttribute . En ese caso, todas las llamadas a los miembros de la clase se sincronizan automáticamente y el dominio de sincronización es el cuerpo completo del código de la clase. Si el código de la pila de llamadas de un miembro llama al método y especifica para , el subproceso sale del dominio de sincronización, lo que permite que un subproceso bloqueado en una llamada a cualquier miembro del objeto WaitAny true exitContext continúe. Cuando el WaitAny método vuelve, el subproceso que realizó la llamada debe esperar para volver a escribir el dominio de sincronización.

Se aplica a