Compartilhar via


WaitHandle.WaitAny Método

Definição

Aguarda até que todos os elementos na matriz especificada recebam um sinal.

Sobrecargas

WaitAny(WaitHandle[])

Aguarda até que todos os elementos na matriz especificada recebam um sinal.

WaitAny(WaitHandle[], Int32)

Espera qualquer um dos elementos na matriz especificada receber um sinal usando um inteiro com sinal de 32 bits a fim de especificar o intervalo de tempo.

WaitAny(WaitHandle[], TimeSpan)

Aguarda até todos os elementos na matriz especificada receberem um sinal usando um TimeSpan para especificar o intervalo de tempo.

WaitAny(WaitHandle[], Int32, Boolean)

Espera todos os elementos na matriz especificada receberem um sinal, usando um inteiro com sinal de 32 bits para especificar o intervalo de tempo e especificar se deseja sair do domínio de sincronização antes do tempo de espera.

WaitAny(WaitHandle[], TimeSpan, Boolean)

Espera todos os elementos na matriz especificada receberem um sinal, usando um TimeSpan para especificar o intervalo de tempo e especificar se deseja sair do domínio de sincronização antes do tempo de espera.

WaitAny(WaitHandle[])

Origem:
WaitHandle.cs
Origem:
WaitHandle.cs
Origem:
WaitHandle.cs

Aguarda até que todos os elementos na matriz especificada recebam um sinal.

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[]

Uma matriz WaitHandle que contém os objetos que a instância atual aguardará.

Retornos

O índice da matriz do objeto que atendeu à espera.

Exceções

O parâmetro waitHandles é null.

- ou -

Um ou mais dos objetos na matriz waitHandles é null.

O número de objetos em waitHandles é maior do que o sistema permite.

waitHandles é uma matriz sem elementos e a versão do .NET Framework é 1.0 ou 1.1.

A espera foi concluída porque um thread foi encerrado sem liberar um mutex.

waitHandles é uma matriz sem elementos e a versão do .NET Framework é 2.0 ou posterior.

A matriz waitHandles contendo um proxy transparente para um WaitHandle em outro domínio de aplicativo.

Exemplos

O exemplo de código a seguir demonstra a chamada do 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 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).

Comentários

AbandonedMutexExceptioné novo no .NET Framework versão 2.0. Nas versões anteriores, o WaitAny método retornará true se a espera for concluída porque um mutex está abandonado. Um mutex abandonado geralmente indica um erro grave de codificação. No caso de um mutex em todo o sistema, pode indicar que um aplicativo foi encerrado abruptamente (por exemplo, usando o Gerenciador de Tarefas do Windows). A exceção contém informações úteis para depuração.

O WaitAny método lança um AbandonedMutexException somente quando a espera é concluída devido a um mutex abandonado. Se waitHandles contiver um mutex liberado com um número de índice menor do que o mutex abandonado, o WaitAny método será concluído normalmente e a exceção não será gerada.

Observação

Em versões do .NET Framework anteriores à versão 2.0, se um thread for encerrado ou anulado sem liberar explicitamente um Mutexe estiver Mutex no índice 0 (zero) em uma WaitAny matriz em outro thread, o índice retornado por WaitAny será 128 em vez de 0.

Esse método retorna quando qualquer identificador é sinalizado. Se mais de um objeto for sinalizado durante a chamada, o valor retornado será o índice de matriz do objeto sinalizado com o menor valor de índice de todos os objetos sinalizados.

O número máximo de identificadores de espera é 64 e 63 se o thread atual estiver no STA estado.

Chamar essa sobrecarga de método é equivalente a chamar a sobrecarga do WaitAny(WaitHandle[], Int32, Boolean) método e especificar -1 (ou Timeout.Infinite) para e true para millisecondsTimeoutexitContext.

Aplica-se a

WaitAny(WaitHandle[], Int32)

Origem:
WaitHandle.cs
Origem:
WaitHandle.cs
Origem:
WaitHandle.cs

Espera qualquer um dos elementos na matriz especificada receber um sinal usando um inteiro com sinal de 32 bits a fim de especificar o intervalo de tempo.

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[]

Uma matriz WaitHandle que contém os objetos que a instância atual aguardará.

millisecondsTimeout
Int32

O número de milissegundos para aguardar ou Infinite (- 1) para aguardar indefinidamente.

Retornos

O índice de matriz do objeto que atendeu à espera ou WaitTimeout, se nenhum objeto tiver atendido à espera e um tempo de intervalo igual a millisecondsTimeout tiver passado.

Exceções

O parâmetro waitHandles é null.

- ou -

Um ou mais dos objetos na matriz waitHandles é null.

O número de objetos em waitHandles é maior do que o sistema permite.

millisecondsTimeout é um número negativo diferente de -1, que representa um tempo limite infinito.

A espera foi concluída porque um thread foi encerrado sem liberar um mutex.

waitHandles é uma matriz sem elementos.

A matriz waitHandles contendo um proxy transparente para um WaitHandle em outro domínio de aplicativo.

Comentários

Se millisecondsTimeout for zero, o método não bloqueará. Ele testa o estado dos identificadores de espera e retorna imediatamente.

O WaitAny método lança um AbandonedMutexException somente quando a espera é concluída devido a um mutex abandonado. Se waitHandles contiver um mutex liberado com um número de índice menor do que o mutex abandonado, o WaitAny método será concluído normalmente e a exceção não será gerada.

Esse método retorna quando a espera é encerrada, quando qualquer um dos identificadores é sinalizado ou quando ocorre um tempo limite. Se mais de um objeto for sinalizado durante a chamada, o valor retornado será o índice de matriz do objeto sinalizado com o menor valor de índice de todos os objetos sinalizados.

O número máximo de identificadores de espera é 64 e 63 se o thread atual estiver no STA estado.

Chamar essa sobrecarga de método é o mesmo que chamar a WaitAny(WaitHandle[], Int32, Boolean) sobrecarga e especificar false para exitContext.

Aplica-se a

WaitAny(WaitHandle[], TimeSpan)

Origem:
WaitHandle.cs
Origem:
WaitHandle.cs
Origem:
WaitHandle.cs

Aguarda até todos os elementos na matriz especificada receberem um sinal usando um TimeSpan para especificar o intervalo de tempo.

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[]

Uma matriz WaitHandle que contém os objetos que a instância atual aguardará.

timeout
TimeSpan

Um TimeSpan que representa o número de milissegundos para aguardar ou um TimeSpan que representa -1 milissegundos para aguardar indefinidamente.

Retornos

O índice de matriz do objeto que atendeu à espera ou WaitTimeout, se nenhum objeto tiver atendido à espera e um tempo de intervalo igual a timeout tiver passado.

Exceções

O parâmetro waitHandles é null.

- ou -

Um ou mais dos objetos na matriz waitHandles é null.

O número de objetos em waitHandles é maior do que o sistema permite.

timeout é um número negativo diferente de -1 milissegundo, que representa um tempo limite infinito.

- ou -

timeout é maior que Int32.MaxValue.

A espera foi concluída porque um thread foi encerrado sem liberar um mutex.

waitHandles é uma matriz sem elementos.

A matriz waitHandles contendo um proxy transparente para um WaitHandle em outro domínio de aplicativo.

Comentários

Se timeout for zero, o método não bloqueará. Ele testa o estado dos identificadores de espera e retorna imediatamente.

O WaitAny método lança um AbandonedMutexException somente quando a espera é concluída devido a um mutex abandonado. Se waitHandles contiver um mutex liberado com um número de índice menor do que o mutex abandonado, o WaitAny método será concluído normalmente e a exceção não será gerada.

Esse método retorna quando a espera é encerrada, quando qualquer um dos identificadores é sinalizado ou quando ocorre um tempo limite. Se mais de um objeto for sinalizado durante a chamada, o valor retornado será o índice de matriz do objeto sinalizado com o menor valor de índice de todos os objetos sinalizados.

O número máximo de identificadores de espera é 64 e 63 se o thread atual estiver no STA estado.

O valor máximo para timeout é Int32.MaxValue.

Chamar essa sobrecarga de método é o mesmo que chamar a WaitAny(WaitHandle[], TimeSpan, Boolean) sobrecarga e especificar false para exitContext.

Aplica-se a

WaitAny(WaitHandle[], Int32, Boolean)

Origem:
WaitHandle.cs
Origem:
WaitHandle.cs
Origem:
WaitHandle.cs

Espera todos os elementos na matriz especificada receberem um sinal, usando um inteiro com sinal de 32 bits para especificar o intervalo de tempo e especificar se deseja sair do domínio de sincronização antes do tempo de 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[]

Uma matriz WaitHandle que contém os objetos que a instância atual aguardará.

millisecondsTimeout
Int32

O número de milissegundos para aguardar ou Infinite (- 1) para aguardar indefinidamente.

exitContext
Boolean

true para sair do domínio de sincronização do contexto antes do tempo de espera (se estiver em um contexto sincronizado) e readquiri-lo posteriormente; caso contrário, false.

Retornos

O índice de matriz do objeto que atendeu à espera ou WaitTimeout, se nenhum objeto tiver atendido à espera e um tempo de intervalo igual a millisecondsTimeout tiver passado.

Exceções

O parâmetro waitHandles é null.

- ou -

Um ou mais dos objetos na matriz waitHandles é null.

O número de objetos em waitHandles é maior do que o sistema permite.

waitHandles é uma matriz sem elementos e a versão do .NET Framework é 1.0 ou 1.1.

millisecondsTimeout é um número negativo diferente de -1, que representa um tempo limite infinito.

A espera foi concluída porque um thread foi encerrado sem liberar um mutex.

waitHandles é uma matriz sem elementos e a versão do .NET Framework é 2.0 ou posterior.

A matriz waitHandles contendo um proxy transparente para um WaitHandle em outro domínio de aplicativo.

Exemplos

O exemplo de código a seguir demonstra como usar o pool de threads para pesquisar simultaneamente um arquivo em vários discos. Para considerações de espaço, somente o diretório raiz de cada disco é pesquisado.

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

Comentários

Se millisecondsTimeout for zero, o método não bloqueará. Ele testa o estado dos identificadores de espera e retorna imediatamente.

O WaitAny método lança um AbandonedMutexException somente quando a espera é concluída devido a um mutex abandonado. Se waitHandles contiver um mutex liberado com um número de índice menor do que o mutex abandonado, o WaitAny método será concluído normalmente e a exceção não será gerada. Um mutex abandonado geralmente indica um erro grave de codificação. No caso de um mutex em todo o sistema, pode indicar que um aplicativo foi encerrado abruptamente (por exemplo, usando o Gerenciador de Tarefas do Windows). A exceção contém informações úteis para depuração.

Esse método retorna quando a espera é encerrada, quando qualquer um dos identificadores é sinalizado ou quando ocorre um tempo limite. Se mais de um objeto for sinalizado durante a chamada, o valor retornado será o índice de matriz do objeto sinalizado com o menor valor de índice de todos os objetos sinalizados.

O número máximo de identificadores de espera é 64 e 63 se o thread atual estiver no STA estado.

Saindo do contexto

O exitContext parâmetro não tem efeito, a menos que esse método seja chamado de dentro de um contexto gerenciado não padrão. O contexto gerenciado poderá ser não padrão se o thread estiver dentro de uma chamada para uma instância de uma classe derivada de ContextBoundObject. Mesmo que você esteja executando um método em uma classe que não é derivada de ContextBoundObject, como String, você pode estar em um contexto não padrão se um ContextBoundObject estiver em sua pilha no domínio do aplicativo atual.

Quando o código está sendo executado em um contexto não padrão, especificar true para exitContext faz com que o thread saia do contexto gerenciado não padrão (ou seja, fazer a transição para o contexto padrão) antes de executar esse método. O thread retorna ao contexto não padrão original após a conclusão da chamada para esse método.

Sair do contexto pode ser útil quando a classe associada ao contexto tem o SynchronizationAttribute atributo . Nesse caso, todas as chamadas para membros da classe são sincronizadas automaticamente e o domínio de sincronização é todo o corpo do código para a classe . Se o código na pilha de chamadas de um membro chamar esse método e especificar true para exitContext, o thread sairá do domínio de sincronização, o que permitirá que um thread bloqueado em uma chamada para qualquer membro do objeto prossiga. Quando esse método retorna, o thread que fez a chamada deve aguardar para reentrada no domínio de sincronização.

Aplica-se a

WaitAny(WaitHandle[], TimeSpan, Boolean)

Origem:
WaitHandle.cs
Origem:
WaitHandle.cs
Origem:
WaitHandle.cs

Espera todos os elementos na matriz especificada receberem um sinal, usando um TimeSpan para especificar o intervalo de tempo e especificar se deseja sair do domínio de sincronização antes do tempo de 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[]

Uma matriz WaitHandle que contém os objetos que a instância atual aguardará.

timeout
TimeSpan

Um TimeSpan que representa o número de milissegundos para aguardar ou um TimeSpan que representa -1 milissegundos para aguardar indefinidamente.

exitContext
Boolean

true para sair do domínio de sincronização do contexto antes do tempo de espera (se estiver em um contexto sincronizado) e readquiri-lo posteriormente; caso contrário, false.

Retornos

O índice de matriz do objeto que atendeu à espera ou WaitTimeout, se nenhum objeto tiver atendido à espera e um tempo de intervalo igual a timeout tiver passado.

Exceções

O parâmetro waitHandles é null.

- ou -

Um ou mais dos objetos na matriz waitHandles é null.

O número de objetos em waitHandles é maior do que o sistema permite.

waitHandles é uma matriz sem elementos e a versão do .NET Framework é 1.0 ou 1.1.

timeout é um número negativo diferente de -1 milissegundo, que representa um tempo limite infinito.

- ou -

timeout é maior que Int32.MaxValue.

A espera foi concluída porque um thread foi encerrado sem liberar um mutex.

waitHandles é uma matriz sem elementos e a versão do .NET Framework é 2.0 ou posterior.

A matriz waitHandles contendo um proxy transparente para um WaitHandle em outro domínio de aplicativo.

Exemplos

O exemplo de código a seguir demonstra como usar o pool de threads para pesquisar simultaneamente um arquivo em vários discos. Para considerações de espaço, somente o diretório raiz de cada disco é pesquisado.

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

Comentários

Se timeout for zero, o método não bloqueará. Ele testa o estado dos identificadores de espera e retorna imediatamente.

O WaitAny método lança um AbandonedMutexException somente quando a espera é concluída devido a um mutex abandonado. Se waitHandles contiver um mutex liberado com um número de índice menor do que o mutex abandonado, o WaitAny método será concluído normalmente e a exceção não será gerada. Um mutex abandonado geralmente indica um erro grave de codificação. No caso de um mutex em todo o sistema, pode indicar que um aplicativo foi encerrado abruptamente (por exemplo, usando o Gerenciador de Tarefas do Windows). A exceção contém informações úteis para depuração.

Esse método retorna quando a espera é encerrada, quando qualquer um dos identificadores é sinalizado ou quando ocorre um tempo limite. Se mais de um objeto for sinalizado durante a chamada, o valor retornado será o índice de matriz do objeto sinalizado com o menor valor de índice de todos os objetos sinalizados.

O número máximo de identificadores de espera é 64 e 63 se o thread atual estiver no STA estado.

O valor máximo para timeout é Int32.MaxValue.

Saindo do contexto

O exitContext parâmetro não tem efeito, a menos que esse método seja chamado de dentro de um contexto gerenciado não padrão. O contexto gerenciado poderá ser não padrão se o thread estiver dentro de uma chamada para uma instância de uma classe derivada de ContextBoundObject. Mesmo que você esteja executando um método em uma classe que não é derivada de ContextBoundObject, como String, você pode estar em um contexto não padrão se um ContextBoundObject estiver em sua pilha no domínio do aplicativo atual.

Quando o código está sendo executado em um contexto não padrão, especificar true para exitContext faz com que o thread saia do contexto gerenciado não padrão (ou seja, fazer a transição para o contexto padrão) antes de executar esse método. O thread retorna ao contexto não padrão original após a conclusão da chamada para esse método.

Sair do contexto pode ser útil quando a classe associada ao contexto tem o SynchronizationAttribute atributo . Nesse caso, todas as chamadas para membros da classe são sincronizadas automaticamente e o domínio de sincronização é todo o corpo do código para a classe . Se o código na pilha de chamadas de um membro chamar esse método e especificar true para exitContext, o thread sairá do domínio de sincronização, o que permitirá que um thread bloqueado em uma chamada para qualquer membro do objeto prossiga. Quando esse método retorna, o thread que fez a chamada deve aguardar para reentrada no domínio de sincronização.

Aplica-se a