WaitHandle.WaitAny Método
Definição
Importante
Algumas informações se referem a produtos de pré-lançamento que podem ser substancialmente modificados antes do lançamento. A Microsoft não oferece garantias, expressas ou implícitas, das informações aqui fornecidas.
Aguarda que qualquer um dos elementos na matriz especificada receba um sinal.
Sobrecargas
| Nome | Description |
|---|---|
| WaitAny(WaitHandle[]) |
Aguarda que qualquer um dos elementos na matriz especificada receba um sinal. |
| WaitAny(WaitHandle[], Int32) |
Aguarda que qualquer um dos elementos na matriz especificada receba um sinal, usando um inteiro com sinal de 32 bits para especificar o intervalo de tempo. |
| WaitAny(WaitHandle[], TimeSpan) |
Aguarda que qualquer um dos elementos na matriz especificada receba um sinal, usando um TimeSpan para especificar o intervalo de tempo. |
| WaitAny(WaitHandle[], Int32, Boolean) |
Aguarda que qualquer um dos elementos na matriz especificada receba um sinal, usando um inteiro com sinal de 32 bits para especificar o intervalo de tempo e especificando se deseja sair do domínio de sincronização antes da espera. |
| WaitAny(WaitHandle[], TimeSpan, Boolean) |
Aguarda qualquer um dos elementos na matriz especificada receber um sinal, usando um TimeSpan para especificar o intervalo de tempo e especificando se o domínio de sincronização deve ser encerrado antes da espera. |
WaitAny(WaitHandle[])
Aguarda que qualquer um dos elementos na matriz especificada receba 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 WaitHandle matriz que contém os objetos para os quais a instância atual aguardará.
Retornos
O índice de matriz do objeto que satisfize a espera.
Exceções
O waitHandles parâmetro é null.
-ou-
Um ou mais dos objetos na waitHandles matriz é null.
O número de objetos é waitHandles maior do que o 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 waitHandles matriz contém 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 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 de codificação grave. 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 só é gerado AbandonedMutexException 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.
Note
Em versões do .NET Framework anteriores à versão 2.0, se um thread sair ou anular sem liberar explicitamente um Mutex e esse Mutex estiver no índice 0 (zero) em uma matriz WaitAny em outro thread, o índice retornado por WaitAny é 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 millisecondsTimeout e true para exitContext.
Aplica-se a
WaitAny(WaitHandle[], Int32)
Aguarda que qualquer um dos elementos na matriz especificada receba um sinal, usando um inteiro com sinal de 32 bits para 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 WaitHandle matriz que contém os objetos para os quais a instância atual aguardará.
- millisecondsTimeout
- Int32
O número de milissegundos a aguardar ou Infinite (-1) aguardar indefinidamente.
Retornos
O índice de matriz do objeto que satisfizeva a espera ou WaitTimeout se nenhum objeto satisfizeva a espera e um intervalo de tempo equivalente ao millisecondsTimeout que foi passado.
Exceções
O waitHandles parâmetro é null.
-ou-
Um ou mais dos objetos na waitHandles matriz é null.
O número de objetos é waitHandles maior do que o 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 waitHandles matriz contém 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 só é gerado AbandonedMutexException 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)
Aguarda que qualquer um dos elementos na matriz especificada receba 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 WaitHandle matriz que contém os objetos para os quais a instância atual aguardará.
- timeout
- TimeSpan
Um TimeSpan que representa o número de milissegundos a aguardar ou um TimeSpan que representa -1 milissegundos para aguardar indefinidamente.
Retornos
O índice de matriz do objeto que satisfizeva a espera ou WaitTimeout se nenhum objeto satisfizeva a espera e um intervalo de tempo equivalente ao timeout que foi passado.
Exceções
O waitHandles parâmetro é null.
-ou-
Um ou mais dos objetos na waitHandles matriz é null.
O número de objetos é waitHandles maior do que o que o sistema permite.
timeout é um número negativo diferente de -1 milissegundos, 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 waitHandles matriz contém 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 só é gerado AbandonedMutexException 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 termina, 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 é timeoutInt32.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)
Aguarda que qualquer um dos elementos na matriz especificada receba um sinal, usando um inteiro com sinal de 32 bits para especificar o intervalo de tempo e especificando se deseja sair do domínio de sincronização antes da 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 WaitHandle matriz que contém os objetos para os quais a instância atual aguardará.
- millisecondsTimeout
- Int32
O número de milissegundos a aguardar ou Infinite (-1) aguardar indefinidamente.
- exitContext
- Boolean
true para sair do domínio de sincronização para o contexto antes da espera (se em um contexto sincronizado) e requisioná-lo posteriormente; caso contrário, false.
Retornos
O índice de matriz do objeto que satisfizeva a espera ou WaitTimeout se nenhum objeto satisfizeva a espera e um intervalo de tempo equivalente ao millisecondsTimeout que foi passado.
Exceções
O waitHandles parâmetro é null.
-ou-
Um ou mais dos objetos na waitHandles matriz é null.
O número de objetos é waitHandles maior do que o 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 waitHandles matriz contém 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 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 só é gerado AbandonedMutexException 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 de codificação grave. 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 seja derivada de ContextBoundObject, por exemplo String, você poderá estar em um contexto não padrão se estiver ContextBoundObject 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 fazer 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 da classe. Se o código na pilha de chamadas de um membro chamar esse método e especificar trueexitContext, o thread sairá do domínio de sincronização, o que permite 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 recuar novamente no domínio de sincronização.
Aplica-se a
WaitAny(WaitHandle[], TimeSpan, Boolean)
Aguarda qualquer um dos elementos na matriz especificada receber um sinal, usando um TimeSpan para especificar o intervalo de tempo e especificando se o domínio de sincronização deve ser encerrado antes da 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 WaitHandle matriz que contém os objetos para os quais a instância atual aguardará.
- timeout
- TimeSpan
Um TimeSpan que representa o número de milissegundos a aguardar ou um TimeSpan que representa -1 milissegundos para aguardar indefinidamente.
- exitContext
- Boolean
true para sair do domínio de sincronização para o contexto antes da espera (se em um contexto sincronizado) e requisioná-lo posteriormente; caso contrário, false.
Retornos
O índice de matriz do objeto que satisfizeva a espera ou WaitTimeout se nenhum objeto satisfizeva a espera e um intervalo de tempo equivalente ao timeout que foi passado.
Exceções
O waitHandles parâmetro é null.
-ou-
Um ou mais dos objetos na waitHandles matriz é null.
O número de objetos é waitHandles maior do que o 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 milissegundos, 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 waitHandles matriz contém 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 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 só é gerado AbandonedMutexException 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 de codificação grave. 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 termina, 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 é timeoutInt32.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 seja derivada de ContextBoundObject, por exemplo String, você poderá estar em um contexto não padrão se estiver ContextBoundObject 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 fazer 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 da classe. Se o código na pilha de chamadas de um membro chamar esse método e especificar trueexitContext, o thread sairá do domínio de sincronização, o que permite 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 recuar novamente no domínio de sincronização.