WaitHandle.WaitAll Метод
Определение
Важно!
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Ожидает получения сигнала всеми элементами заданного массива.
Перегрузки
WaitAll(WaitHandle[], TimeSpan, Boolean) |
Ожидает получения сигнала всеми элементами заданного массива, используя значение типа TimeSpan для задания интервала времени и указывая, следует ли выйти из домена синхронизации до начала ожидания. |
WaitAll(WaitHandle[], Int32, Boolean) |
Ожидает получения сигнала всеми элементами заданного массива, используя значение типа Int32 для задания интервала времени и указывая, следует ли выйти из домена синхронизации до начала ожидания. |
WaitAll(WaitHandle[], TimeSpan) |
Ожидает получения сигнала всеми элементами заданного массива, используя значение TimeSpan для указания интервала времени. |
WaitAll(WaitHandle[], Int32) |
Ожидает получения сигнала всеми элементами заданного массива, используя значение Int32 для указания интервала времени. |
WaitAll(WaitHandle[]) |
Ожидает получения сигнала всеми элементами заданного массива. |
WaitAll(WaitHandle[], TimeSpan, Boolean)
- Исходный код:
- WaitHandle.cs
- Исходный код:
- WaitHandle.cs
- Исходный код:
- WaitHandle.cs
Ожидает получения сигнала всеми элементами заданного массива, используя значение типа TimeSpan для задания интервала времени и указывая, следует ли выйти из домена синхронизации до начала ожидания.
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
Параметры
- waitHandles
- WaitHandle[]
Массив WaitHandle
, содержащий объекты, ожидаемые текущим экземпляром. Этот массив не может содержать несколько ссылок на один и тот же объект.
- timeout
- TimeSpan
Объект TimeSpan, представляющий время ожидания в миллисекундах, или объект TimeSpan, представляющий -1 миллисекунду для неограниченного ожидания.
- exitContext
- Boolean
Значение true
для выхода из домена синхронизации в текущем контексте перед ожиданием (в синхронизированном контексте) с его последующим повторным получением; в противном случае — false
.
Возвращаемое значение
Значение true
, когда каждый элемент массива waitHandles
получил сигнал; иначе — false
.
Исключения
Параметр waitHandles
имеет значение null
.
-или-
Один или несколько объектов массива waitHandles
имеют значение null
.
-или-
Массив waitHandles
не содержит элементов, и используется платформа .NET Framework версии 2.0 или более поздней.
Массив waitHandles
содержит повторяющиеся элементы.
Массив waitHandles
содержит больше объектов, чем разрешено системой.
-или-
Атрибут STAThreadAttribute применяется к процедуре потока для текущего потока, а массив waitHandles
содержит более одного элемента.
Массив waitHandles
не содержит элементов, и используется платформа .NET Framework версии 1.0 или 1.1.
timeout
является отрицательным числом, отличным от -1 миллисекунды, которое представляет неограниченное время ожидания.
-или-
timeout
больше, чем Int32.MaxValue.
Ожидание прервано, так как поток завершил работу, не освободив мьютекс.
Массив waitHandles
содержит прозрачный прокси для элемента WaitHandle в другом домене приложения.
Примеры
В следующем примере кода показано, как использовать пул потоков для асинхронного создания и записи в группу файлов. Каждая операция записи помещается в очередь как рабочий элемент и сигнализирует о ее завершении. Основной поток ожидает, пока все элементы будут сигнализировать, а затем завершает работу.
using namespace System;
using namespace System::IO;
using namespace System::Security::Permissions;
using namespace System::Threading;
// Maintain state to pass to WriteToFile.
ref class State
{
public:
String^ fileName;
array<Byte>^byteArray;
ManualResetEvent^ manualEvent;
State( String^ fileName, array<Byte>^byteArray, ManualResetEvent^ manualEvent )
: fileName( fileName ), byteArray( byteArray ), manualEvent( manualEvent )
{}
};
ref class Writer
{
private:
static int workItemCount = 0;
Writer(){}
public:
static void WriteToFile( Object^ state )
{
int workItemNumber = workItemCount;
Interlocked::Increment( workItemCount );
Console::WriteLine( "Starting work item {0}.", workItemNumber.ToString() );
State^ stateInfo = dynamic_cast<State^>(state);
FileStream^ fileWriter;
// Create and write to the file.
try
{
fileWriter = gcnew FileStream( stateInfo->fileName,FileMode::Create );
fileWriter->Write( stateInfo->byteArray, 0, stateInfo->byteArray->Length );
}
finally
{
if ( fileWriter != nullptr )
{
fileWriter->Close();
}
// Signal main() that the work item has finished.
Console::WriteLine( "Ending work item {0}.", workItemNumber.ToString() );
stateInfo->manualEvent->Set();
}
}
};
int main()
{
const int numberOfFiles = 5;
String^ dirName = "C:\\TestTest";
String^ fileName;
array<Byte>^byteArray;
Random^ randomGenerator = gcnew Random;
array<ManualResetEvent^>^manualEvents = gcnew array<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 = gcnew array<Byte>(1000000);
randomGenerator->NextBytes( byteArray );
manualEvents[ i ] = gcnew ManualResetEvent( false );
stateInfo = gcnew State( fileName,byteArray,manualEvents[ i ] );
ThreadPool::QueueUserWorkItem( gcnew WaitCallback( &Writer::WriteToFile ), stateInfo );
}
// Since ThreadPool threads are background threads,
// wait for the work items to signal before exiting.
if ( WaitHandle::WaitAll( manualEvents, TimeSpan(0,0,5), false ) )
{
Console::WriteLine( "Files written - main exiting." );
}
else
{
// The wait operation times out.
Console::WriteLine( "Error writing files - main exiting." );
}
}
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
Комментарии
Если timeout
равно нулю, метод не блокируется. Он проверяет состояние дескрипторов ожидания и возвращается немедленно.
При отказе от мьютекса AbandonedMutexException создается исключение . Отказ от мьютекса часто указывает на серьезную ошибку кодирования. В случае системного мьютекса это может означать, что приложение было внезапно завершено (например, с помощью диспетчера задач Windows). Исключение содержит сведения, полезные для отладки.
Метод WaitAll возвращает, когда ожидание завершается. Это означает, что все дескрипторы получают сигнал или возникает время ожидания. Если передается более 64 дескрипторов, NotSupportedException возникает исключение . Если массив содержит дубликаты, вызов завершится ошибкой.
Максимальное значение для timeout
— Int32.MaxValue.
Выход из контекста
Параметр exitContext
не действует, если этот метод не вызывается из нестандартного управляемого контекста. Управляемый контекст может быть неразрешен, если поток находится внутри вызова экземпляра класса, производного от ContextBoundObject. Даже если вы в настоящее время выполняете метод в классе, который не является производным от ContextBoundObject, например String, вы можете находиться в контексте, не являющемся стандартным, если ContextBoundObject находится в стеке в текущем домене приложения.
При выполнении кода в контексте, не являющегося стандартным, указание true
для exitContext
приводит к тому, что перед выполнением этого метода поток выйдет из нестандартного управляемого контекста (т. е. для перехода в контекст по умолчанию). Поток возвращается в исходный контекст nondefault после завершения вызова этого метода.
Выход из контекста может быть полезен, если связанный с контекстом класс имеет SynchronizationAttribute атрибут . В этом случае все вызовы членов класса синхронизируются автоматически, а домен синхронизации — это весь текст кода для класса. Если код в стеке вызовов true
члена вызывает этот метод и указывает для exitContext
, поток выходит из домена синхронизации, что позволяет потоку, заблокированном при вызове любого члена объекта, продолжить работу. При возврате этого метода поток, который сделал вызов, должен дождаться повторного ввести домен синхронизации.
Применяется к
WaitAll(WaitHandle[], Int32, Boolean)
- Исходный код:
- WaitHandle.cs
- Исходный код:
- WaitHandle.cs
- Исходный код:
- WaitHandle.cs
Ожидает получения сигнала всеми элементами заданного массива, используя значение типа Int32 для задания интервала времени и указывая, следует ли выйти из домена синхронизации до начала ожидания.
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
Параметры
- waitHandles
- WaitHandle[]
Массив WaitHandle
, содержащий объекты, ожидаемые текущим экземпляром. Данный массив не может содержать несколько ссылок на один и тот же объект (дубликатов).
- millisecondsTimeout
- Int32
Время ожидания в миллисекундах или функция Infinite (-1) в случае неограниченного времени ожидания.
- exitContext
- Boolean
Значение true
для выхода из домена синхронизации в текущем контексте перед ожиданием (в синхронизированном контексте) с его последующим повторным получением; в противном случае — false
.
Возвращаемое значение
Значение true
, если каждый элемент массива waitHandles
получил сигнал; в противном случае значение false
.
Исключения
Параметр waitHandles
имеет значение null
.
-или-
Один или несколько объектов массива waitHandles
имеют значение null
.
-или-
Массив waitHandles
не содержит элементов, и используется платформа .NET Framework версии 2.0 или более поздней.
Массив waitHandles
содержит повторяющиеся элементы.
Массив waitHandles
содержит больше объектов, чем разрешено системой.
-или-
Текущий поток находится в состоянии STA, а waitHandles
содержит несколько элементов.
Массив waitHandles
не содержит элементов, и используется платформа .NET Framework версии 1.0 или 1.1.
Параметр millisecondsTimeout
является отрицательным числом, отличным от –1, что означает бесконечное время ожидания.
Ожидание закончилось, так как поток завершил работу, не освободив мьютекс.
Массив waitHandles
содержит прозрачный прокси для элемента WaitHandle в другом домене приложения.
Примеры
В следующем примере кода показано, как использовать пул потоков для асинхронного создания и записи в группу файлов. Каждая операция записи помещается в очередь как рабочий элемент и сигнализирует о ее завершении. Основной поток ожидает, пока все элементы будут сигнализировать, а затем завершает работу.
using namespace System;
using namespace System::IO;
using namespace System::Security::Permissions;
using namespace System::Threading;
// Maintain state to pass to WriteToFile.
ref class State
{
public:
String^ fileName;
array<Byte>^byteArray;
ManualResetEvent^ manualEvent;
State( String^ fileName, array<Byte>^byteArray, ManualResetEvent^ manualEvent )
: fileName( fileName ), byteArray( byteArray ), manualEvent( manualEvent )
{}
};
ref class Writer
{
private:
static int workItemCount = 0;
Writer(){}
public:
static void WriteToFile( Object^ state )
{
int workItemNumber = workItemCount;
Interlocked::Increment( workItemCount );
Console::WriteLine( "Starting work item {0}.", workItemNumber.ToString() );
State^ stateInfo = dynamic_cast<State^>(state);
FileStream^ fileWriter;
// Create and write to the file.
try
{
fileWriter = gcnew FileStream( stateInfo->fileName,FileMode::Create );
fileWriter->Write( stateInfo->byteArray, 0, stateInfo->byteArray->Length );
}
finally
{
if ( fileWriter != nullptr )
{
fileWriter->Close();
}
// Signal main() that the work item has finished.
Console::WriteLine( "Ending work item {0}.", workItemNumber.ToString() );
stateInfo->manualEvent->Set();
}
}
};
int main()
{
const int numberOfFiles = 5;
String^ dirName = "C:\\TestTest";
String^ fileName;
array<Byte>^byteArray;
Random^ randomGenerator = gcnew Random;
array<ManualResetEvent^>^manualEvents = gcnew array<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 = gcnew array<Byte>(1000000);
randomGenerator->NextBytes( byteArray );
manualEvents[ i ] = gcnew ManualResetEvent( false );
stateInfo = gcnew State( fileName,byteArray,manualEvents[ i ] );
ThreadPool::QueueUserWorkItem( gcnew 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." );
}
}
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
Комментарии
Если millisecondsTimeout
равно нулю, метод не блокируется. Он проверяет состояние дескрипторов ожидания и возвращается немедленно.
При отказе от мьютекса AbandonedMutexException создается исключение . Отказ от мьютекса часто указывает на серьезную ошибку кодирования. В случае системного мьютекса это может означать, что приложение было внезапно завершено (например, с помощью диспетчера задач Windows). Исключение содержит сведения, полезные для отладки.
Метод WaitAll возвращает значение , когда ожидание завершается, то есть, когда все дескрипторы сигнализируют, или при истечении времени ожидания. Если передается более 64 дескрипторов, NotSupportedException возникает исключение . Если в массиве есть дубликаты, вызов завершается ошибкой DuplicateWaitObjectExceptionс .
Выход из контекста
Параметр exitContext
не действует, если этот метод не вызывается из нестандартного управляемого контекста. Управляемый контекст может быть неразрешен, если поток находится внутри вызова экземпляра класса, производного от ContextBoundObject. Даже если вы в настоящее время выполняете метод в классе, который не является производным от ContextBoundObject, например String, вы можете находиться в контексте, не являющемся стандартным, если ContextBoundObject находится в стеке в текущем домене приложения.
При выполнении кода в контексте, не являющегося стандартным, указание true
для exitContext
приводит к тому, что перед выполнением этого метода поток выйдет из нестандартного управляемого контекста (т. е. для перехода в контекст по умолчанию). Поток возвращается в исходный контекст nondefault после завершения вызова этого метода.
Выход из контекста может быть полезен, если связанный с контекстом класс имеет SynchronizationAttribute атрибут . В этом случае все вызовы членов класса синхронизируются автоматически, а домен синхронизации — это весь текст кода для класса. Если код в стеке вызовов true
члена вызывает этот метод и указывает для exitContext
, поток выходит из домена синхронизации, что позволяет потоку, заблокированном при вызове любого члена объекта, продолжить работу. При возврате этого метода поток, который сделал вызов, должен дождаться повторного ввести домен синхронизации.
Применяется к
WaitAll(WaitHandle[], TimeSpan)
- Исходный код:
- WaitHandle.cs
- Исходный код:
- WaitHandle.cs
- Исходный код:
- WaitHandle.cs
Ожидает получения сигнала всеми элементами заданного массива, используя значение TimeSpan для указания интервала времени.
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
Параметры
- waitHandles
- WaitHandle[]
Массив WaitHandle
, содержащий объекты, ожидаемые текущим экземпляром. Этот массив не может содержать несколько ссылок на один и тот же объект.
- timeout
- TimeSpan
Объект TimeSpan, представляющий время ожидания в миллисекундах, или объект TimeSpan, представляющий -1 миллисекунду для неограниченного ожидания.
Возвращаемое значение
Значение true
, если каждый элемент массива waitHandles
получил сигнал; в противном случае значение false
.
Исключения
Параметр waitHandles
имеет значение null
.
-или-
Один или несколько объектов массива waitHandles
имеют значение null
.
-или-
В массиве waitHandles
отсутствуют элементы.
Массив waitHandles
содержит повторяющиеся элементы.
Примечание. В .NET для приложений Магазина Windows или в переносимой библиотеке классов перехватите исключение базового класса ArgumentException.
Массив waitHandles
содержит больше объектов, чем разрешено системой.
-или-
Текущий поток находится в состоянии STA, а waitHandles
содержит несколько элементов.
timeout
является отрицательным числом, отличным от -1 миллисекунды, которое представляет неограниченное время ожидания.
-или-
timeout
больше, чем Int32.MaxValue.
Ожидание прервано, так как поток завершил работу, не освободив мьютекс.
Массив waitHandles
содержит прозрачный прокси для элемента WaitHandle в другом домене приложения.
Комментарии
Если timeout
равно нулю, метод не блокируется. Он проверяет состояние дескрипторов ожидания и возвращается немедленно.
Метод WaitAll возвращает, когда ожидание завершается. Это означает, что все дескрипторы получают сигнал или возникает время ожидания. Если передается более 64 дескрипторов, NotSupportedException возникает исключение . Если массив содержит дубликаты, вызов завершится ошибкой.
Максимальное значение для timeout
— Int32.MaxValue.
Вызов перегрузки этого метода совпадает с вызовом перегрузки WaitAll(WaitHandle[], TimeSpan, Boolean) и указанием false
для exitContext
.
Применяется к
WaitAll(WaitHandle[], Int32)
- Исходный код:
- WaitHandle.cs
- Исходный код:
- WaitHandle.cs
- Исходный код:
- WaitHandle.cs
Ожидает получения сигнала всеми элементами заданного массива, используя значение Int32 для указания интервала времени.
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
Параметры
- waitHandles
- WaitHandle[]
Массив WaitHandle
, содержащий объекты, ожидаемые текущим экземпляром. Данный массив не может содержать несколько ссылок на один и тот же объект (дубликатов).
- millisecondsTimeout
- Int32
Время ожидания в миллисекундах или функция Infinite (-1) в случае неограниченного времени ожидания.
Возвращаемое значение
Значение true
, если каждый элемент массива waitHandles
получил сигнал; в противном случае значение false
.
Исключения
Параметр waitHandles
имеет значение null
.
-или-
Один или несколько объектов массива waitHandles
имеют значение null
.
-или-
В массиве waitHandles
отсутствуют элементы.
Массив waitHandles
содержит повторяющиеся элементы.
Примечание. В .NET для приложений Магазина Windows или в переносимой библиотеке классов перехватите исключение базового класса ArgumentException.
Массив waitHandles
содержит больше объектов, чем разрешено системой.
-или-
Текущий поток находится в состоянии STA, а waitHandles
содержит несколько элементов.
Параметр millisecondsTimeout
является отрицательным числом, отличным от –1, что означает бесконечное время ожидания.
Ожидание закончилось, так как поток завершил работу, не освободив мьютекс.
Массив waitHandles
содержит прозрачный прокси для элемента WaitHandle в другом домене приложения.
Комментарии
Если millisecondsTimeout
равно нулю, метод не блокируется. Он проверяет состояние дескрипторов ожидания и возвращается немедленно.
Метод WaitAll возвращает значение , когда ожидание завершается, то есть, когда все дескрипторы сигнализируют, или при истечении времени ожидания. Если передается более 64 дескрипторов, NotSupportedException возникает исключение . Если в массиве есть дубликаты, вызов завершается ошибкой DuplicateWaitObjectExceptionс .
Вызов перегрузки этого метода совпадает с вызовом перегрузки WaitAll(WaitHandle[], Int32, Boolean) и указанием false
для exitContext
.
Применяется к
WaitAll(WaitHandle[])
- Исходный код:
- WaitHandle.cs
- Исходный код:
- WaitHandle.cs
- Исходный код:
- WaitHandle.cs
Ожидает получения сигнала всеми элементами заданного массива.
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
Параметры
- waitHandles
- WaitHandle[]
Массив WaitHandle
, содержащий объекты, ожидаемые текущим экземпляром. Этот массив не может содержать несколько ссылок на один и тот же объект.
Возвращаемое значение
true
, когда каждый элемент waitHandles
получил сигнал. В противном случае возврат из метода не происходит.
Исключения
Параметр waitHandles
имеет значение null
. -или-
Один или несколько объектов массива waitHandles
имеют значение null
.
-или-
Массив waitHandles
не содержит элементов, и используется платформа .NET Framework версии 2.0 или более поздней.
Массив waitHandles
содержит повторяющиеся элементы.
Примечание. В .NET для приложений Магазина Windows или в переносимой библиотеке классов перехватите исключение базового класса ArgumentException.
Массив waitHandles
содержит больше объектов, чем разрешено системой.
-или-
Текущий поток находится в состоянии STA, а waitHandles
содержит несколько элементов.
Массив waitHandles
не содержит элементов, и используется платформа .NET Framework версии 1.0 или 1.1.
Ожидание прервано, так как поток завершил работу, не освободив мьютекс.
Массив waitHandles
содержит прозрачный прокси для элемента WaitHandle в другом домене приложения.
Примеры
В следующем примере кода показано, как использовать пул потоков для асинхронного создания и записи в группу файлов. Каждая операция записи помещается в очередь как рабочий элемент и сигнализирует о ее завершении. Основной поток ожидает, пока все элементы будут сигнализировать, а затем завершает работу.
using namespace System;
using namespace System::IO;
using namespace System::Security::Permissions;
using namespace System::Threading;
ref class State
{
public:
String^ fileName;
array<Byte>^byteArray;
ManualResetEvent^ manualEvent;
State( String^ fileName, array<Byte>^byteArray, ManualResetEvent^ manualEvent )
: fileName( fileName ), byteArray( byteArray ), manualEvent( manualEvent )
{}
};
ref class Writer
{
private:
static int workItemCount = 0;
Writer(){}
public:
static void WriteToFile( Object^ state )
{
int workItemNumber = workItemCount;
Interlocked::Increment( workItemCount );
Console::WriteLine( "Starting work item {0}.", workItemNumber.ToString() );
State^ stateInfo = dynamic_cast<State^>(state);
FileStream^ fileWriter;
// Create and write to the file.
try
{
fileWriter = gcnew FileStream( stateInfo->fileName,FileMode::Create );
fileWriter->Write( stateInfo->byteArray, 0, stateInfo->byteArray->Length );
}
finally
{
if ( fileWriter != nullptr )
{
fileWriter->Close();
}
// Signal main() that the work item has finished.
Console::WriteLine( "Ending work item {0}.", workItemNumber.ToString() );
stateInfo->manualEvent->Set();
}
}
};
void main()
{
const int numberOfFiles = 5;
String^ dirName = "C:\\TestTest";
String^ fileName;
array<Byte>^byteArray;
Random^ randomGenerator = gcnew Random;
array<ManualResetEvent^>^manualEvents = gcnew array<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 = gcnew array<Byte>(1000000);
randomGenerator->NextBytes( byteArray );
manualEvents[ i ] = gcnew ManualResetEvent( false );
stateInfo = gcnew State( fileName,byteArray,manualEvents[ i ] );
ThreadPool::QueueUserWorkItem( gcnew 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." );
}
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
Комментарии
AbandonedMutexException является новым в .NET Framework версии 2.0. В предыдущих версиях метод возвращает значение true
при WaitAll отказе от мьютекса. Отказ от мьютекса часто указывает на серьезную ошибку кодирования. В случае системного мьютекса это может означать, что приложение было внезапно завершено (например, с помощью диспетчера задач Windows). Исключение содержит сведения, полезные для отладки.
Метод WaitAll возвращает, когда все дескрипторы получают сигнал. Если передается более 64 дескрипторов, NotSupportedException возникает исключение . Если массив содержит дубликаты, вызов завершается ошибкой DuplicateWaitObjectExceptionс .
Вызов перегрузки этого метода эквивалентен вызову перегрузки WaitAll(WaitHandle[], Int32, Boolean) метода и указанию -1 (или Timeout.Infinite) для millisecondsTimeout
и true
для exitContext
.