WaitHandle.WaitAll Método
Definição
Importante
Algumas informações dizem respeito a um produto pré-lançado que pode ser substancialmente modificado antes de ser lançado. A Microsoft não faz garantias, de forma expressa ou implícita, em relação à informação aqui apresentada.
Espera que todos os elementos do array especificado recebam um sinal.
Sobrecargas
| Name | Description |
|---|---|
| WaitAll(WaitHandle[], TimeSpan, Boolean) |
Espera que todos os elementos do array especificado recebam um sinal, usando um TimeSpan valor para especificar o intervalo de tempo, e especificando se deve sair do domínio de sincronização antes da espera. |
| WaitAll(WaitHandle[], Int32, Boolean) |
Espera que todos os elementos do array especificado recebam um sinal, usando um Int32 valor para especificar o intervalo de tempo e especificando se deve sair do domínio de sincronização antes da espera. |
| WaitAll(WaitHandle[], TimeSpan) |
Espera que todos os elementos do array especificado recebam um sinal, usando um TimeSpan valor para especificar o intervalo de tempo. |
| WaitAll(WaitHandle[], Int32) |
Espera que todos os elementos do array especificado recebam um sinal, usando um Int32 valor para especificar o intervalo de tempo. |
| WaitAll(WaitHandle[]) |
Espera que todos os elementos do array especificado recebam um sinal. |
WaitAll(WaitHandle[], TimeSpan, Boolean)
Espera que todos os elementos do array especificado recebam um sinal, usando um TimeSpan valor para especificar o intervalo de tempo, e especificando se deve sair do domínio de sincronização antes da espera.
public:
static bool WaitAll(cli::array <System::Threading::WaitHandle ^> ^ waitHandles, TimeSpan timeout, bool exitContext);
public static bool WaitAll(System.Threading.WaitHandle[] waitHandles, TimeSpan timeout, bool exitContext);
static member WaitAll : System.Threading.WaitHandle[] * TimeSpan * bool -> bool
Public Shared Function WaitAll (waitHandles As WaitHandle(), timeout As TimeSpan, exitContext As Boolean) As Boolean
Parâmetros
- waitHandles
- WaitHandle[]
Um WaitHandle array contendo os objetos para os quais a instância atual irá esperar. Este array não pode conter múltiplas referências ao mesmo objeto.
- timeout
- TimeSpan
A TimeSpan que representa o número de milissegundos para esperar, ou a TimeSpan que representa -1 milissegundos, para esperar indefinidamente.
- exitContext
- Boolean
true sair do domínio de sincronização do contexto antes da espera (se estiver num contexto sincronizado), e readquiri-lo depois; caso contrário, false.
Devoluções
true quando cada elemento em waitHandles recebeu um sinal; caso contrário false.
Exceções
O waitHandles parâmetro é null.
-ou-
Um ou mais dos objetos do waitHandles array é null.
-ou-
waitHandles é um array sem elementos e a versão .NET Framework é 2.0 ou posterior.
O waitHandles array contém elementos que são duplicados.
O número de objetos em waitHandles é maior do que o sistema permite.
-ou-
O STAThreadAttribute atributo é aplicado ao procedimento de thread para o thread atual e waitHandles contém mais do que um elemento.
waitHandles é um array sem elementos e a versão .NET Framework é 1.0 ou 1.1.
timeout é um número negativo diferente de -1 milissegundos, o que representa um tempo de espera infinito.
-ou-
timeout é maior do que Int32.MaxValue.
A espera terminou porque um tópico saiu sem divulgar um mutex.
O waitHandles array contém um proxy transparente para um WaitHandle noutro domínio de aplicação.
Exemplos
O exemplo de código seguinte mostra como usar o pool de threads para criar e escrever assíncronamente num grupo de ficheiros. Cada operação de escrita é colocada em fila como um item de trabalho e sinaliza quando está concluída. O tópico principal espera que todos os itens sinalizem e depois sai.
using System;
using System.IO;
using System.Security.Permissions;
using System.Threading;
class Test
{
static void Main()
{
const int numberOfFiles = 5;
string dirName = @"C:\TestTest";
string fileName;
byte[] byteArray;
Random randomGenerator = new Random();
ManualResetEvent[] manualEvents =
new ManualResetEvent[numberOfFiles];
State stateInfo;
if(!Directory.Exists(dirName))
{
Directory.CreateDirectory(dirName);
}
// Queue the work items that create and write to the files.
for(int i = 0; i < numberOfFiles; i++)
{
fileName = string.Concat(
dirName, @"\Test", i.ToString(), ".dat");
// Create random data to write to the file.
byteArray = new byte[1000000];
randomGenerator.NextBytes(byteArray);
manualEvents[i] = new ManualResetEvent(false);
stateInfo =
new State(fileName, byteArray, manualEvents[i]);
ThreadPool.QueueUserWorkItem(new WaitCallback(
Writer.WriteToFile), stateInfo);
}
// Since ThreadPool threads are background threads,
// wait for the work items to signal before exiting.
if(WaitHandle.WaitAll(
manualEvents, new TimeSpan(0, 0, 5), false))
{
Console.WriteLine("Files written - main exiting.");
}
else
{
// The wait operation times out.
Console.WriteLine("Error writing files - main exiting.");
}
}
}
// Maintain state to pass to WriteToFile.
class State
{
public string fileName;
public byte[] byteArray;
public ManualResetEvent manualEvent;
public State(string fileName, byte[] byteArray,
ManualResetEvent manualEvent)
{
this.fileName = fileName;
this.byteArray = byteArray;
this.manualEvent = manualEvent;
}
}
class Writer
{
static int workItemCount = 0;
Writer() {}
public static void WriteToFile(object state)
{
int workItemNumber = workItemCount;
Interlocked.Increment(ref workItemCount);
Console.WriteLine("Starting work item {0}.",
workItemNumber.ToString());
State stateInfo = (State)state;
FileStream fileWriter = null;
// Create and write to the file.
try
{
fileWriter = new FileStream(
stateInfo.fileName, FileMode.Create);
fileWriter.Write(stateInfo.byteArray,
0, stateInfo.byteArray.Length);
}
finally
{
if(fileWriter != null)
{
fileWriter.Close();
}
// Signal Main that the work item has finished.
Console.WriteLine("Ending work item {0}.",
workItemNumber.ToString());
stateInfo.manualEvent.Set();
}
}
}
Imports System.IO
Imports System.Security.Permissions
Imports System.Threading
Public Class Test
' WaitHandle.WaitAll requires a multithreaded apartment
' when using multiple wait handles.
<MTAThreadAttribute> _
Shared Sub Main()
Const numberOfFiles As Integer = 5
Dim dirName As String = "C:\TestTest"
Dim fileName As String
Dim byteArray() As Byte
Dim randomGenerator As New Random()
Dim manualEvents(numberOfFiles - 1) As ManualResetEvent
Dim stateInfo As State
If Directory.Exists(dirName) <> True Then
Directory.CreateDirectory(dirName)
End If
' Queue the work items that create and write to the files.
For i As Integer = 0 To numberOfFiles - 1
fileName = String.Concat( _
dirName, "\Test", i.ToString(), ".dat")
' Create random data to write to the file.
byteArray = New Byte(1000000){}
randomGenerator.NextBytes(byteArray)
manualEvents(i) = New ManualResetEvent(false)
stateInfo = _
New State(fileName, byteArray, manualEvents(i))
ThreadPool.QueueUserWorkItem(AddressOf _
Writer.WriteToFile, stateInfo)
Next i
' Since ThreadPool threads are background threads,
' wait for the work items to signal before exiting.
If WaitHandle.WaitAll( _
manualEvents, New TimeSpan(0, 0, 5), false) = True Then
Console.WriteLine("Files written - main exiting.")
Else
' The wait operation times out.
Console.WriteLine("Error writing files - main exiting.")
End If
End Sub
End Class
' Maintain state to pass to WriteToFile.
Public Class State
Public fileName As String
Public byteArray As Byte()
Public manualEvent As ManualResetEvent
Sub New(fileName As String, byteArray() As Byte, _
manualEvent As ManualResetEvent)
Me.fileName = fileName
Me.byteArray = byteArray
Me.manualEvent = manualEvent
End Sub
End Class
Public Class Writer
Private Sub New()
End Sub
Shared workItemCount As Integer = 0
Shared Sub WriteToFile(state As Object)
Dim workItemNumber As Integer = workItemCount
Interlocked.Increment(workItemCount)
Console.WriteLine("Starting work item {0}.", _
workItemNumber.ToString())
Dim stateInfo As State = CType(state, State)
Dim fileWriter As FileStream = Nothing
' Create and write to the file.
Try
fileWriter = New FileStream( _
stateInfo.fileName, FileMode.Create)
fileWriter.Write(stateInfo.byteArray, _
0, stateInfo.byteArray.Length)
Finally
If Not fileWriter Is Nothing Then
fileWriter.Close()
End If
' Signal Main that the work item has finished.
Console.WriteLine("Ending work item {0}.", _
workItemNumber.ToString())
stateInfo.manualEvent.Set()
End Try
End Sub
End Class
Observações
Se timeout for zero, o método não bloqueia. Testa o estado dos controlos de espera e retorna imediatamente.
Se um mutex for abandonado, um AbandonedMutexException é lançado. Um mutex abandonado indica frequentemente um erro grave de codificação. No caso de um mutex em todo o sistema, pode indicar que uma aplicação foi terminada abruptamente (por exemplo, usando o Gestor de Tarefas do Windows). A exceção contém informações úteis para depuração.
O WaitAll método retorna quando a espera termina, o que significa que ou todos os handles são sinalizados ou ocorre um time-out. Se mais de 64 alças forem passadas, é lançado a.NotSupportedException Se o array contiver duplicados, a chamada falhará.
O valor máximo para timeout é Int32.MaxValue.
Saindo do contexto
O exitContext parâmetro não tem efeito a menos que este método seja chamado dentro de um contexto gerido não predefinido. O contexto gerido pode ser não padrão se o seu thread estiver dentro de uma chamada para uma instância de uma classe derivada de ContextBoundObject. Mesmo que esteja atualmente a executar um método numa classe que não deriva de ContextBoundObject, como String, pode estar num contexto não padrão se a ContextBoundObject estiver na sua pilha no domínio de aplicação atual.
Quando o seu código está a ser executado num contexto não padrão, especificar true para exitContext faz com que o thread saia do contexto gerido não padrão (isto é, para transitar para o contexto padrão) antes de executar este método. O thread regressa ao contexto original não padrão após a conclusão da chamada a este método.
Sair do contexto pode ser útil quando a classe ligada 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 de código da classe. Se o código na pilha de chamadas de um membro chamar este método e especificar true para exitContext, o thread sai do domínio de sincronização, o que permite que um thread bloqueado numa chamada para qualquer membro do objeto prossiga. Quando este método regressa, o thread que fez a chamada tem de esperar para reentrar no domínio de sincronização.
Aplica-se a
WaitAll(WaitHandle[], Int32, Boolean)
Espera que todos os elementos do array especificado recebam um sinal, usando um Int32 valor para especificar o intervalo de tempo e especificando se deve sair do domínio de sincronização antes da espera.
public:
static bool WaitAll(cli::array <System::Threading::WaitHandle ^> ^ waitHandles, int millisecondsTimeout, bool exitContext);
public static bool WaitAll(System.Threading.WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext);
static member WaitAll : System.Threading.WaitHandle[] * int * bool -> bool
Public Shared Function WaitAll (waitHandles As WaitHandle(), millisecondsTimeout As Integer, exitContext As Boolean) As Boolean
Parâmetros
- waitHandles
- WaitHandle[]
Um WaitHandle array contendo os objetos para os quais a instância atual irá esperar. Este array não pode conter múltiplas referências ao mesmo objeto (duplicados).
- millisecondsTimeout
- Int32
O número de milissegundos para esperar, ou Infinite (-1) para esperar indefinidamente.
- exitContext
- Boolean
true sair do domínio de sincronização do contexto antes da espera (se estiver num contexto sincronizado), e readquiri-lo depois; caso contrário, false.
Devoluções
true quando cada elemento em waitHandles recebeu um sinal; caso contrário, false.
Exceções
O waitHandles parâmetro é null.
-ou-
Um ou mais dos objetos do waitHandles array é null.
-ou-
waitHandles é um array sem elementos e a versão .NET Framework é 2.0 ou posterior.
O waitHandles array contém elementos que são duplicados.
O número de objetos em waitHandles é maior do que o sistema permite.
-ou-
A thread atual está em STA estado e waitHandles contém mais do que um elemento.
waitHandles é um array sem elementos e a versão .NET Framework é 1.0 ou 1.1.
millisecondsTimeout é um número negativo diferente de -1, o que representa um tempo limite infinito.
A espera terminou porque um tópico saiu sem divulgar um mutex.
O waitHandles array contém um proxy transparente para um WaitHandle noutro domínio de aplicação.
Exemplos
O exemplo de código seguinte mostra como usar o pool de threads para criar e escrever assíncronamente num grupo de ficheiros. Cada operação de escrita é colocada em fila como um item de trabalho e sinaliza quando está concluída. O tópico principal espera que todos os itens sinalizem e depois sai.
using System;
using System.IO;
using System.Security.Permissions;
using System.Threading;
class Test
{
static void Main()
{
const int numberOfFiles = 5;
string dirName = @"C:\TestTest";
string fileName;
byte[] byteArray;
Random randomGenerator = new Random();
ManualResetEvent[] manualEvents =
new ManualResetEvent[numberOfFiles];
State stateInfo;
if(!Directory.Exists(dirName))
{
Directory.CreateDirectory(dirName);
}
// Queue the work items that create and write to the files.
for(int i = 0; i < numberOfFiles; i++)
{
fileName = string.Concat(
dirName, @"\Test", i.ToString(), ".dat");
// Create random data to write to the file.
byteArray = new byte[1000000];
randomGenerator.NextBytes(byteArray);
manualEvents[i] = new ManualResetEvent(false);
stateInfo =
new State(fileName, byteArray, manualEvents[i]);
ThreadPool.QueueUserWorkItem(new WaitCallback(
Writer.WriteToFile), stateInfo);
}
// Since ThreadPool threads are background threads,
// wait for the work items to signal before exiting.
if(WaitHandle.WaitAll(manualEvents, 5000, false))
{
Console.WriteLine("Files written - main exiting.");
}
else
{
// The wait operation times out.
Console.WriteLine("Error writing files - main exiting.");
}
}
}
// Maintain state to pass to WriteToFile.
class State
{
public string fileName;
public byte[] byteArray;
public ManualResetEvent manualEvent;
public State(string fileName, byte[] byteArray,
ManualResetEvent manualEvent)
{
this.fileName = fileName;
this.byteArray = byteArray;
this.manualEvent = manualEvent;
}
}
class Writer
{
static int workItemCount = 0;
Writer() {}
public static void WriteToFile(object state)
{
int workItemNumber = workItemCount;
Interlocked.Increment(ref workItemCount);
Console.WriteLine("Starting work item {0}.",
workItemNumber.ToString());
State stateInfo = (State)state;
FileStream fileWriter = null;
// Create and write to the file.
try
{
fileWriter = new FileStream(
stateInfo.fileName, FileMode.Create);
fileWriter.Write(stateInfo.byteArray,
0, stateInfo.byteArray.Length);
}
finally
{
if(fileWriter != null)
{
fileWriter.Close();
}
// Signal Main that the work item has finished.
Console.WriteLine("Ending work item {0}.",
workItemNumber.ToString());
stateInfo.manualEvent.Set();
}
}
}
Imports System.IO
Imports System.Security.Permissions
Imports System.Threading
Public Class Test
' WaitHandle.WaitAll requires a multithreaded apartment
' when using multiple wait handles.
<MTAThreadAttribute> _
Shared Sub Main()
Const numberOfFiles As Integer = 5
Dim dirName As String = "C:\TestTest"
Dim fileName As String
Dim byteArray() As Byte
Dim randomGenerator As New Random()
Dim manualEvents(numberOfFiles - 1) As ManualResetEvent
Dim stateInfo As State
If Directory.Exists(dirName) <> True Then
Directory.CreateDirectory(dirName)
End If
' Queue the work items that create and write to the files.
For i As Integer = 0 To numberOfFiles - 1
fileName = String.Concat( _
dirName, "\Test", i.ToString(), ".dat")
' Create random data to write to the file.
byteArray = New Byte(1000000){}
randomGenerator.NextBytes(byteArray)
manualEvents(i) = New ManualResetEvent(false)
stateInfo = _
New State(fileName, byteArray, manualEvents(i))
ThreadPool.QueueUserWorkItem(AddressOf _
Writer.WriteToFile, stateInfo)
Next i
' Since ThreadPool threads are background threads,
' wait for the work items to signal before exiting.
If WaitHandle.WaitAll(manualEvents, 5000, false) = True Then
Console.WriteLine("Files written - main exiting.")
Else
' The wait operation times out.
Console.WriteLine("Error writing files - main exiting.")
End If
End Sub
End Class
' Maintain state to pass to WriteToFile.
Public Class State
Public fileName As String
Public byteArray As Byte()
Public manualEvent As ManualResetEvent
Sub New(fileName As String, byteArray() As Byte, _
manualEvent As ManualResetEvent)
Me.fileName = fileName
Me.byteArray = byteArray
Me.manualEvent = manualEvent
End Sub
End Class
Public Class Writer
Private Sub New()
End Sub
Shared workItemCount As Integer = 0
Shared Sub WriteToFile(state As Object)
Dim workItemNumber As Integer = workItemCount
Interlocked.Increment(workItemCount)
Console.WriteLine("Starting work item {0}.", _
workItemNumber.ToString())
Dim stateInfo As State = CType(state, State)
Dim fileWriter As FileStream = Nothing
' Create and write to the file.
Try
fileWriter = New FileStream( _
stateInfo.fileName, FileMode.Create)
fileWriter.Write(stateInfo.byteArray, _
0, stateInfo.byteArray.Length)
Finally
If Not fileWriter Is Nothing Then
fileWriter.Close()
End If
' Signal Main that the work item has finished.
Console.WriteLine("Ending work item {0}.", _
workItemNumber.ToString())
stateInfo.manualEvent.Set()
End Try
End Sub
End Class
Observações
Se millisecondsTimeout for zero, o método não bloqueia. Testa o estado dos controlos de espera e retorna imediatamente.
Se um mutex for abandonado, um AbandonedMutexException é lançado. Um mutex abandonado indica frequentemente um erro grave de codificação. No caso de um mutex em todo o sistema, pode indicar que uma aplicação foi terminada abruptamente (por exemplo, usando o Gestor de Tarefas do Windows). A exceção contém informações úteis para depuração.
O WaitAll método retorna quando a espera termina, o que significa quando todos os handles são sinalizados ou quando ocorre o time-out. Se mais de 64 alças forem passadas, é lançado a.NotSupportedException Se existirem duplicados no array, a chamada falha com um DuplicateWaitObjectException.
Saindo do contexto
O exitContext parâmetro não tem efeito a menos que este método seja chamado dentro de um contexto gerido não predefinido. O contexto gerido pode ser não padrão se o seu thread estiver dentro de uma chamada para uma instância de uma classe derivada de ContextBoundObject. Mesmo que esteja atualmente a executar um método numa classe que não deriva de ContextBoundObject, como String, pode estar num contexto não padrão se a ContextBoundObject estiver na sua pilha no domínio de aplicação atual.
Quando o seu código está a ser executado num contexto não padrão, especificar true para exitContext faz com que o thread saia do contexto gerido não padrão (isto é, para transitar para o contexto padrão) antes de executar este método. O thread regressa ao contexto original não padrão após a conclusão da chamada a este método.
Sair do contexto pode ser útil quando a classe ligada 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 de código da classe. Se o código na pilha de chamadas de um membro chamar este método e especificar true para exitContext, o thread sai do domínio de sincronização, o que permite que um thread bloqueado numa chamada para qualquer membro do objeto prossiga. Quando este método regressa, o thread que fez a chamada tem de esperar para reentrar no domínio de sincronização.
Aplica-se a
WaitAll(WaitHandle[], TimeSpan)
Espera que todos os elementos do array especificado recebam um sinal, usando um TimeSpan valor para especificar o intervalo de tempo.
public:
static bool WaitAll(cli::array <System::Threading::WaitHandle ^> ^ waitHandles, TimeSpan timeout);
public static bool WaitAll(System.Threading.WaitHandle[] waitHandles, TimeSpan timeout);
static member WaitAll : System.Threading.WaitHandle[] * TimeSpan -> bool
Public Shared Function WaitAll (waitHandles As WaitHandle(), timeout As TimeSpan) As Boolean
Parâmetros
- waitHandles
- WaitHandle[]
Um WaitHandle array contendo os objetos para os quais a instância atual irá esperar. Este array não pode conter múltiplas referências ao mesmo objeto.
- timeout
- TimeSpan
A TimeSpan que representa o número de milissegundos para esperar, ou a TimeSpan que representa -1 milissegundos, para esperar indefinidamente.
Devoluções
true quando cada elemento em waitHandles recebeu um sinal; caso contrário, false.
Exceções
O waitHandles parâmetro é null.
-ou-
Um ou mais dos objetos do waitHandles array é null.
-ou-
waitHandles é um array sem elementos.
O waitHandles array contém elementos que são duplicados.
Nota: No .NET para Windows aplicações da Store ou na Portable Class Library, apanhe a exceção da classe base, ArgumentException, em vez disso.
O número de objetos em waitHandles é maior do que o sistema permite.
-ou-
A thread atual está em STA estado e waitHandles contém mais do que um elemento.
timeout é um número negativo diferente de -1 milissegundos, o que representa um tempo de espera infinito.
-ou-
timeout é maior do que Int32.MaxValue.
A espera terminou porque um tópico saiu sem divulgar um mutex.
O waitHandles array contém um proxy transparente para um WaitHandle noutro domínio de aplicação.
Observações
Se timeout for zero, o método não bloqueia. Testa o estado dos controlos de espera e retorna imediatamente.
O WaitAll método retorna quando a espera termina, o que significa que ou todos os handles são sinalizados ou ocorre um time-out. Se mais de 64 alças forem passadas, é lançado a.NotSupportedException Se o array contiver duplicados, a chamada falhará.
O valor máximo para timeout é Int32.MaxValue.
Chamar a este método overload é o mesmo que chamar a WaitAll(WaitHandle[], TimeSpan, Boolean) overload e especificar false para exitContext.
Aplica-se a
WaitAll(WaitHandle[], Int32)
Espera que todos os elementos do array especificado recebam um sinal, usando um Int32 valor para especificar o intervalo de tempo.
public:
static bool WaitAll(cli::array <System::Threading::WaitHandle ^> ^ waitHandles, int millisecondsTimeout);
public static bool WaitAll(System.Threading.WaitHandle[] waitHandles, int millisecondsTimeout);
static member WaitAll : System.Threading.WaitHandle[] * int -> bool
Public Shared Function WaitAll (waitHandles As WaitHandle(), millisecondsTimeout As Integer) As Boolean
Parâmetros
- waitHandles
- WaitHandle[]
Um WaitHandle array contendo os objetos para os quais a instância atual irá esperar. Este array não pode conter múltiplas referências ao mesmo objeto (duplicados).
- millisecondsTimeout
- Int32
O número de milissegundos para esperar, ou Infinite (-1) para esperar indefinidamente.
Devoluções
true quando cada elemento em waitHandles recebeu um sinal; caso contrário, false.
Exceções
O waitHandles parâmetro é null.
-ou-
Um ou mais dos objetos do waitHandles array é null.
-ou-
waitHandles é um array sem elementos.
O waitHandles array contém elementos que são duplicados.
Nota: No .NET para Windows aplicações da Store ou na Portable Class Library, apanhe a exceção da classe base, ArgumentException, em vez disso.
O número de objetos em waitHandles é maior do que o sistema permite.
-ou-
A thread atual está em STA estado e waitHandles contém mais do que um elemento.
millisecondsTimeout é um número negativo diferente de -1, o que representa um tempo limite infinito.
A espera terminou porque um tópico saiu sem divulgar um mutex.
O waitHandles array contém um proxy transparente para um WaitHandle noutro domínio de aplicação.
Observações
Se millisecondsTimeout for zero, o método não bloqueia. Testa o estado dos controlos de espera e retorna imediatamente.
O WaitAll método retorna quando a espera termina, o que significa quando todos os handles são sinalizados ou quando ocorre o time-out. Se mais de 64 alças forem passadas, é lançado a.NotSupportedException Se existirem duplicados no array, a chamada falha com um DuplicateWaitObjectException.
Chamar a este método overload é o mesmo que chamar a WaitAll(WaitHandle[], Int32, Boolean) overload e especificar false para exitContext.
Aplica-se a
WaitAll(WaitHandle[])
Espera que todos os elementos do array especificado recebam um sinal.
public:
static bool WaitAll(cli::array <System::Threading::WaitHandle ^> ^ waitHandles);
public static bool WaitAll(System.Threading.WaitHandle[] waitHandles);
static member WaitAll : System.Threading.WaitHandle[] -> bool
Public Shared Function WaitAll (waitHandles As WaitHandle()) As Boolean
Parâmetros
- waitHandles
- WaitHandle[]
Um WaitHandle array contendo os objetos para os quais a instância atual irá esperar. Este array não pode conter múltiplas referências ao mesmo objeto.
Devoluções
true quando cada elemento em waitHandles recebeu um sinal; caso contrário, o método nunca retorna.
Exceções
O waitHandles parâmetro é null. -ou-
Um ou mais dos objetos no waitHandles array são null.
-ou-
waitHandles é um array sem elementos e a versão .NET Framework é 2.0 ou posterior.
O waitHandles array contém elementos que são duplicados.
Nota: No .NET para Windows aplicações da Store ou na Portable Class Library, apanhe a exceção da classe base, ArgumentException, em vez disso.
O número de objetos em waitHandles é maior do que o sistema permite.
-ou-
A thread atual está em STA estado e waitHandles contém mais do que um elemento.
waitHandles é um array sem elementos e a versão .NET Framework é 1.0 ou 1.1.
A espera terminou porque um tópico saiu sem divulgar um mutex.
O waitHandles array contém um proxy transparente para um WaitHandle noutro domínio de aplicação.
Exemplos
O exemplo de código seguinte mostra como usar o pool de threads para criar e escrever assíncronamente num grupo de ficheiros. Cada operação de escrita é colocada em fila como um item de trabalho e sinaliza quando está concluída. O tópico principal espera que todos os itens sinalizem e depois sai.
using System;
using System.IO;
using System.Security.Permissions;
using System.Threading;
class Test
{
static void Main()
{
const int numberOfFiles = 5;
string dirName = @"C:\TestTest";
string fileName;
byte[] byteArray;
Random randomGenerator = new Random();
ManualResetEvent[] manualEvents =
new ManualResetEvent[numberOfFiles];
State stateInfo;
if(!Directory.Exists(dirName))
{
Directory.CreateDirectory(dirName);
}
// Queue the work items that create and write to the files.
for(int i = 0; i < numberOfFiles; i++)
{
fileName = string.Concat(
dirName, @"\Test", i.ToString(), ".dat");
// Create random data to write to the file.
byteArray = new byte[1000000];
randomGenerator.NextBytes(byteArray);
manualEvents[i] = new ManualResetEvent(false);
stateInfo =
new State(fileName, byteArray, manualEvents[i]);
ThreadPool.QueueUserWorkItem(new WaitCallback(
Writer.WriteToFile), stateInfo);
}
// Since ThreadPool threads are background threads,
// wait for the work items to signal before exiting.
WaitHandle.WaitAll(manualEvents);
Console.WriteLine("Files written - main exiting.");
}
}
// Maintain state to pass to WriteToFile.
class State
{
public string fileName;
public byte[] byteArray;
public ManualResetEvent manualEvent;
public State(string fileName, byte[] byteArray,
ManualResetEvent manualEvent)
{
this.fileName = fileName;
this.byteArray = byteArray;
this.manualEvent = manualEvent;
}
}
class Writer
{
static int workItemCount = 0;
Writer() {}
public static void WriteToFile(object state)
{
int workItemNumber = workItemCount;
Interlocked.Increment(ref workItemCount);
Console.WriteLine("Starting work item {0}.",
workItemNumber.ToString());
State stateInfo = (State)state;
FileStream fileWriter = null;
// Create and write to the file.
try
{
fileWriter = new FileStream(
stateInfo.fileName, FileMode.Create);
fileWriter.Write(stateInfo.byteArray,
0, stateInfo.byteArray.Length);
}
finally
{
if(fileWriter != null)
{
fileWriter.Close();
}
// Signal Main that the work item has finished.
Console.WriteLine("Ending work item {0}.",
workItemNumber.ToString());
stateInfo.manualEvent.Set();
}
}
}
Imports System.IO
Imports System.Security.Permissions
Imports System.Threading
Public Class Test
' WaitHandle.WaitAll requires a multithreaded apartment
' when using multiple wait handles.
<MTAThreadAttribute> _
Shared Sub Main()
Const numberOfFiles As Integer = 5
Dim dirName As String = "C:\TestTest"
Dim fileName As String
Dim byteArray() As Byte
Dim randomGenerator As New Random()
Dim manualEvents(numberOfFiles - 1) As ManualResetEvent
Dim stateInfo As State
If Directory.Exists(dirName) <> True Then
Directory.CreateDirectory(dirName)
End If
' Queue the work items that create and write to the files.
For i As Integer = 0 To numberOfFiles - 1
fileName = String.Concat( _
dirName, "\Test", i.ToString(), ".dat")
' Create random data to write to the file.
byteArray = New Byte(1000000){}
randomGenerator.NextBytes(byteArray)
manualEvents(i) = New ManualResetEvent(false)
stateInfo = _
New State(fileName, byteArray, manualEvents(i))
ThreadPool.QueueUserWorkItem(AddressOf _
Writer.WriteToFile, stateInfo)
Next i
' Since ThreadPool threads are background threads,
' wait for the work items to signal before exiting.
WaitHandle.WaitAll(manualEvents)
Console.WriteLine("Files written - main exiting.")
End Sub
End Class
' Maintain state to pass to WriteToFile.
Public Class State
Public fileName As String
Public byteArray As Byte()
Public manualEvent As ManualResetEvent
Sub New(fileName As String, byteArray() As Byte, _
manualEvent As ManualResetEvent)
Me.fileName = fileName
Me.byteArray = byteArray
Me.manualEvent = manualEvent
End Sub
End Class
Public Class Writer
Private Sub New()
End Sub
Shared workItemCount As Integer = 0
Shared Sub WriteToFile(state As Object)
Dim workItemNumber As Integer = workItemCount
Interlocked.Increment(workItemCount)
Console.WriteLine("Starting work item {0}.", _
workItemNumber.ToString())
Dim stateInfo As State = CType(state, State)
Dim fileWriter As FileStream = Nothing
' Create and write to the file.
Try
fileWriter = New FileStream( _
stateInfo.fileName, FileMode.Create)
fileWriter.Write(stateInfo.byteArray, _
0, stateInfo.byteArray.Length)
Finally
If Not fileWriter Is Nothing Then
fileWriter.Close()
End If
' Signal Main that the work item has finished.
Console.WriteLine("Ending work item {0}.", _
workItemNumber.ToString())
stateInfo.manualEvent.Set()
End Try
End Sub
End Class
Observações
AbandonedMutexException é novo na versão 2.0 do .NET Framework. Em versões anteriores, o WaitAll método retorna true quando um mutex é abandonado. Um mutex abandonado indica frequentemente um erro grave de codificação. No caso de um mutex em todo o sistema, pode indicar que uma aplicação foi terminada abruptamente (por exemplo, usando o Gestor de Tarefas do Windows). A exceção contém informações úteis para depuração.
O WaitAll método retorna quando todas as alças são sinalizadas. Se mais de 64 alças forem passadas, é lançado a.NotSupportedException Se o array contiver duplicados, a chamada falha com um DuplicateWaitObjectException.
Chamar a este método overload é equivalente a chamar o WaitAll(WaitHandle[], Int32, Boolean) método overload e especificar -1 (ou Timeout.Infinite) para millisecondsTimeout e true para exitContext.