Поделиться через


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 возникает исключение . Если массив содержит дубликаты, вызов завершится ошибкой.

Примечание

Метод WaitAll не поддерживается в потоках в STA состоянии.

Максимальное значение для timeoutInt32.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с .

Примечание

Метод WaitAll не поддерживается в потоках в STA состоянии.

Выход из контекста

Параметр 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 возникает исключение . Если массив содержит дубликаты, вызов завершится ошибкой.

Примечание

Метод WaitAll не поддерживается в потоках в STA состоянии.

Максимальное значение для timeoutInt32.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 не поддерживается в потоках в STA состоянии.

Вызов перегрузки этого метода совпадает с вызовом перегрузки 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 не поддерживается в потоках в STA состоянии.

Вызов перегрузки этого метода эквивалентен вызову перегрузки WaitAll(WaitHandle[], Int32, Boolean) метода и указанию -1 (или Timeout.Infinite) для millisecondsTimeout и true для exitContext.

Применяется к