WaitHandle.WaitAny Метод

Определение

Ожидает получения сигнала какими-либо элементами заданного массива.

Перегрузки

WaitAny(WaitHandle[])

Ожидает получения сигнала какими-либо элементами заданного массива.

WaitAny(WaitHandle[], Int32)

Ожидает получения сигнала любыми элементами указанного массива, используя 32-разрядное целое число со знаком для задания интервала времени.

WaitAny(WaitHandle[], TimeSpan)

Ожидает получения сигнала любыми элементами заданного массива, используя значение типа TimeSpan для указания интервала времени.

WaitAny(WaitHandle[], Int32, Boolean)

Ожидает, пока какой-либо из элементов заданного массива не получит сигнал, используя 32-разрядное целое число со знаком для задания интервала времени и определения, нужно ли осуществить выход из домена синхронизации до окончания ожидания.

WaitAny(WaitHandle[], TimeSpan, Boolean)

Ожидает получения сигнала какими-либо элементами заданного массива, используя TimeSpan для задания интервала времени и указывая, следует ли выйти из домена синхронизации до начала ожидания.

WaitAny(WaitHandle[])

Ожидает получения сигнала какими-либо элементами заданного массива.

public:
 static int WaitAny(cli::array <System::Threading::WaitHandle ^> ^ waitHandles);
public static int WaitAny (System.Threading.WaitHandle[] waitHandles);
static member WaitAny : System.Threading.WaitHandle[] -> int
Public Shared Function WaitAny (waitHandles As WaitHandle()) As Integer

Параметры

waitHandles
WaitHandle[]

Массив WaitHandle, содержащий объекты, ожидаемые текущим экземпляром.

Возвращаемое значение

Индекс объекта, удовлетворившего операцию ожидания, в массиве.

Исключения

Параметр waitHandles имеет значение null.

-или-

Один или несколько объектов массива waitHandles имеют значение null.

Массив waitHandles содержит больше объектов, чем разрешено системой.

waitHandles является массивом без элементов, а платформа .NET Framework имеет версию 1.0 или 1.1.

Ожидание закончилось, так как поток завершил работу, не освободив мьютекс.

waitHandles является массивом без элементов, а платформа .NET Framework имеет версию 2.0 или выше.

Массив waitHandles содержит прозрачный прокси для элемента WaitHandle в другом домене приложения.

Примеры

В следующем примере кода демонстрируется WaitAny вызов метода .

using namespace System;
using namespace System::Threading;

public ref class WaitHandleExample
{
    // Define a random number generator for testing.
private:
    static Random^ random = gcnew Random();
public:
    static void DoTask(Object^ state)
    {
        AutoResetEvent^ autoReset = (AutoResetEvent^) state;
        int time = 1000 * random->Next(2, 10);
        Console::WriteLine("Performing a task for {0} milliseconds.", time);
        Thread::Sleep(time);
        autoReset->Set();
    }
};

int main()
{
    // Define an array with two AutoResetEvent WaitHandles.
    array<WaitHandle^>^ handles = gcnew array<WaitHandle^> {
        gcnew AutoResetEvent(false), gcnew AutoResetEvent(false)};

    // Queue up two tasks on two different threads;
    // wait until all tasks are completed.
    DateTime timeInstance = DateTime::Now;
    Console::WriteLine("Main thread is waiting for BOTH tasks to " +
        "complete.");
    ThreadPool::QueueUserWorkItem(
        gcnew WaitCallback(WaitHandleExample::DoTask), handles[0]);
    ThreadPool::QueueUserWorkItem(
        gcnew WaitCallback(WaitHandleExample::DoTask), handles[1]);
    WaitHandle::WaitAll(handles);
    // The time shown below should match the longest task.
    Console::WriteLine("Both tasks are completed (time waited={0})",
        (DateTime::Now - timeInstance).TotalMilliseconds);

    // Queue up two tasks on two different threads;
    // wait until any tasks are completed.
    timeInstance = DateTime::Now;
    Console::WriteLine();
    Console::WriteLine("The main thread is waiting for either task to " +
        "complete.");
    ThreadPool::QueueUserWorkItem(
        gcnew WaitCallback(WaitHandleExample::DoTask), handles[0]);
    ThreadPool::QueueUserWorkItem(
        gcnew WaitCallback(WaitHandleExample::DoTask), handles[1]);
    int index = WaitHandle::WaitAny(handles);
    // The time shown below should match the shortest task.
    Console::WriteLine("Task {0} finished first (time waited={1}).",
        index + 1, (DateTime::Now - timeInstance).TotalMilliseconds);
}

// This code produces the following sample output.
//
// Main thread is waiting for BOTH tasks to complete.
// Performing a task for 7000 milliseconds.
// Performing a task for 4000 milliseconds.
// Both tasks are completed (time waited=7064.8052)

// The main thread is waiting for either task to complete.
// Performing a task for 2000 milliseconds.
// Performing a task for 2000 milliseconds.
// Task 1 finished first (time waited=2000.6528).
using System;
using System.Threading;

public sealed class App
{
    // Define an array with two AutoResetEvent WaitHandles.
    static WaitHandle[] waitHandles = new WaitHandle[]
    {
        new AutoResetEvent(false),
        new AutoResetEvent(false)
    };

    // Define a random number generator for testing.
    static Random r = new Random();

    static void Main()
    {
        // Queue up two tasks on two different threads;
        // wait until all tasks are completed.
        DateTime dt = DateTime.Now;
        Console.WriteLine("Main thread is waiting for BOTH tasks to complete.");
        ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[0]);
        ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[1]);
        WaitHandle.WaitAll(waitHandles);
        // The time shown below should match the longest task.
        Console.WriteLine("Both tasks are completed (time waited={0})",
            (DateTime.Now - dt).TotalMilliseconds);

        // Queue up two tasks on two different threads;
        // wait until any task is completed.
        dt = DateTime.Now;
        Console.WriteLine();
        Console.WriteLine("The main thread is waiting for either task to complete.");
        ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[0]);
        ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[1]);
        int index = WaitHandle.WaitAny(waitHandles);
        // The time shown below should match the shortest task.
        Console.WriteLine("Task {0} finished first (time waited={1}).",
            index + 1, (DateTime.Now - dt).TotalMilliseconds);
    }

    static void DoTask(Object state)
    {
        AutoResetEvent are = (AutoResetEvent) state;
        int time = 1000 * r.Next(2, 10);
        Console.WriteLine("Performing a task for {0} milliseconds.", time);
        Thread.Sleep(time);
        are.Set();
    }
}

// This code produces output similar to the following:
//
//  Main thread is waiting for BOTH tasks to complete.
//  Performing a task for 7000 milliseconds.
//  Performing a task for 4000 milliseconds.
//  Both tasks are completed (time waited=7064.8052)
//
//  The main thread is waiting for either task to complete.
//  Performing a task for 2000 milliseconds.
//  Performing a task for 2000 milliseconds.
//  Task 1 finished first (time waited=2000.6528).
Imports System.Threading

NotInheritable Public Class App
    ' Define an array with two AutoResetEvent WaitHandles.
    Private Shared waitHandles() As WaitHandle = _
        {New AutoResetEvent(False), New AutoResetEvent(False)}
    
    ' Define a random number generator for testing.
    Private Shared r As New Random()
    
    <MTAThreadAttribute> _
    Public Shared Sub Main() 
        ' Queue two tasks on two different threads; 
        ' wait until all tasks are completed.
        Dim dt As DateTime = DateTime.Now
        Console.WriteLine("Main thread is waiting for BOTH tasks to complete.")
        ThreadPool.QueueUserWorkItem(AddressOf DoTask, waitHandles(0))
        ThreadPool.QueueUserWorkItem(AddressOf DoTask, waitHandles(1))
        WaitHandle.WaitAll(waitHandles)
        ' The time shown below should match the longest task.
        Console.WriteLine("Both tasks are completed (time waited={0})", _
            (DateTime.Now - dt).TotalMilliseconds)
        
        ' Queue up two tasks on two different threads; 
        ' wait until any tasks are completed.
        dt = DateTime.Now
        Console.WriteLine()
        Console.WriteLine("The main thread is waiting for either task to complete.")
        ThreadPool.QueueUserWorkItem(AddressOf DoTask, waitHandles(0))
        ThreadPool.QueueUserWorkItem(AddressOf DoTask, waitHandles(1))
        Dim index As Integer = WaitHandle.WaitAny(waitHandles)
        ' The time shown below should match the shortest task.
        Console.WriteLine("Task {0} finished first (time waited={1}).", _
            index + 1,(DateTime.Now - dt).TotalMilliseconds)
    
    End Sub
    
    Shared Sub DoTask(ByVal state As [Object]) 
        Dim are As AutoResetEvent = CType(state, AutoResetEvent)
        Dim time As Integer = 1000 * r.Next(2, 10)
        Console.WriteLine("Performing a task for {0} milliseconds.", time)
        Thread.Sleep(time)
        are.Set()
    
    End Sub
End Class

' This code produces output similar to the following:
'
'  Main thread is waiting for BOTH tasks to complete.
'  Performing a task for 7000 milliseconds.
'  Performing a task for 4000 milliseconds.
'  Both tasks are completed (time waited=7064.8052)
' 
'  The main thread is waiting for either task to complete.
'  Performing a task for 2000 milliseconds.
'  Performing a task for 2000 milliseconds.
'  Task 1 finished first (time waited=2000.6528).

Комментарии

AbandonedMutexExceptionявляется новым в платформа .NET Framework версии 2.0. В предыдущих версиях метод возвращает значение true , WaitAny если ожидание завершается из-за отказа от мьютекса. Отказ от мьютекса часто указывает на серьезную ошибку кодирования. В случае системного мьютекса это может означать, что приложение было внезапно завершено (например, с помощью диспетчера задач Windows). Исключение содержит сведения, полезные для отладки.

Метод WaitAny создает исключение AbandonedMutexException только после завершения ожидания из-за отказа от мьютекса. Если waitHandles содержит освобожденный мьютекс с более низким номером индекса, чем прерванный мьютекс, WaitAny метод завершается обычным образом и исключение не создается.

Примечание

В версиях платформа .NET Framework более ранней, чем версия 2.0, если поток завершается или прерывается без явного освобождения Mutexи Mutex имеет индекс 0 (нуль) в массиве в WaitAny другом потоке, индекс, возвращаемый методомWaitAny, равен 128, а не 0.

Этот метод возвращает значение при сигнале любого дескриптора. Если во время вызова подается сигнал о нескольких объектах, возвращаемое значение представляет собой индекс массива сигнального объекта с наименьшим значением индекса из всех сигнальных объектов.

Максимальное число дескрипторов ожидания — 64 и 63, если текущий поток находится в STA состоянии.

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

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

WaitAny(WaitHandle[], Int32)

Ожидает получения сигнала любыми элементами указанного массива, используя 32-разрядное целое число со знаком для задания интервала времени.

public:
 static int WaitAny(cli::array <System::Threading::WaitHandle ^> ^ waitHandles, int millisecondsTimeout);
public static int WaitAny (System.Threading.WaitHandle[] waitHandles, int millisecondsTimeout);
static member WaitAny : System.Threading.WaitHandle[] * int -> int
Public Shared Function WaitAny (waitHandles As WaitHandle(), millisecondsTimeout As Integer) As Integer

Параметры

waitHandles
WaitHandle[]

Массив WaitHandle, содержащий объекты, ожидаемые текущим экземпляром.

millisecondsTimeout
Int32

Время ожидания в миллисекундах или функция Infinite (-1) в случае неограниченного времени ожидания.

Возвращаемое значение

Индекс объекта в массиве, удовлетворившего условиям ожидания, или значение WaitTimeout, если ни один из объектов не удовлетворил условиям ожидания и истек интервал времени, равный millisecondsTimeout.

Исключения

Параметр waitHandles имеет значение null.

-или-

Один или несколько объектов массива waitHandles имеют значение null.

Массив waitHandles содержит больше объектов, чем разрешено системой.

Параметр millisecondsTimeout является отрицательным числом, отличным от –1, что означает бесконечное время ожидания.

Ожидание закончилось, так как поток завершил работу, не освободив мьютекс.

В массиве waitHandles отсутствуют элементы.

Массив waitHandles содержит прозрачный прокси для элемента WaitHandle в другом домене приложения.

Комментарии

Если millisecondsTimeout равно нулю, метод не блокируется. Он проверяет состояние дескрипторов ожидания и возвращается немедленно.

Метод WaitAny создает исключение AbandonedMutexException только после завершения ожидания из-за отказа от мьютекса. Если waitHandles содержит освобожденный мьютекс с более низким номером индекса, чем прерванный мьютекс, WaitAny метод завершается обычным образом и исключение не создается.

Этот метод возвращает значение, когда ожидание завершается, когда сигнализирует какой-либо из дескрипторов, или при истечении времени ожидания. Если во время вызова подается сигнал о нескольких объектах, возвращаемое значение представляет собой индекс массива сигнального объекта с наименьшим значением индекса из всех сигнальных объектов.

Максимальное число дескрипторов ожидания — 64 и 63, если текущий поток находится в STA состоянии.

Вызов перегрузки этого метода совпадает с вызовом перегрузки WaitAny(WaitHandle[], Int32, Boolean) и указанием false для exitContext.

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

WaitAny(WaitHandle[], TimeSpan)

Ожидает получения сигнала любыми элементами заданного массива, используя значение типа TimeSpan для указания интервала времени.

public:
 static int WaitAny(cli::array <System::Threading::WaitHandle ^> ^ waitHandles, TimeSpan timeout);
public static int WaitAny (System.Threading.WaitHandle[] waitHandles, TimeSpan timeout);
static member WaitAny : System.Threading.WaitHandle[] * TimeSpan -> int
Public Shared Function WaitAny (waitHandles As WaitHandle(), timeout As TimeSpan) As Integer

Параметры

waitHandles
WaitHandle[]

Массив WaitHandle, содержащий объекты, ожидаемые текущим экземпляром.

timeout
TimeSpan

Период TimeSpan, представляющий время ожидания в миллисекундах, или период TimeSpan, представляющий -1 миллисекунду для неограниченного ожидания.

Возвращаемое значение

Индекс объекта в массиве, удовлетворившего условиям ожидания, или значение WaitTimeout, если ни один из объектов не удовлетворил условиям ожидания и истек интервал времени, равный timeout.

Исключения

Параметр waitHandles имеет значение null.

-или-

Один или несколько объектов массива waitHandles имеют значение null.

Массив waitHandles содержит больше объектов, чем разрешено системой.

timeout является отрицательным числом, отличным от -1 миллисекунды, которое представляет неограниченное время ожидания.

-или-

timeout больше, чем Int32.MaxValue.

Ожидание закончилось, так как поток завершил работу, не освободив мьютекс.

В массиве waitHandles отсутствуют элементы.

Массив waitHandles содержит прозрачный прокси для элемента WaitHandle в другом домене приложения.

Комментарии

Если timeout равно нулю, метод не блокируется. Он проверяет состояние дескрипторов ожидания и возвращается немедленно.

Метод WaitAny создает исключение AbandonedMutexException только после завершения ожидания из-за отказа от мьютекса. Если waitHandles содержит освобожденный мьютекс с более низким номером индекса, чем прерванный мьютекс, WaitAny метод завершается обычным образом и исключение не создается.

Этот метод возвращает значение, когда ожидание завершается, когда сигнализирует какой-либо из дескрипторов, или при истечении времени ожидания. Если во время вызова подается сигнал о нескольких объектах, возвращаемое значение представляет собой индекс массива сигнального объекта с наименьшим значением индекса из всех сигнальных объектов.

Максимальное число дескрипторов ожидания — 64 и 63, если текущий поток находится в STA состоянии.

Максимальное значение для timeoutInt32.MaxValue.

Вызов перегрузки этого метода совпадает с вызовом перегрузки WaitAny(WaitHandle[], TimeSpan, Boolean) и указанием false для exitContext.

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

WaitAny(WaitHandle[], Int32, Boolean)

Ожидает, пока какой-либо из элементов заданного массива не получит сигнал, используя 32-разрядное целое число со знаком для задания интервала времени и определения, нужно ли осуществить выход из домена синхронизации до окончания ожидания.

public:
 static int WaitAny(cli::array <System::Threading::WaitHandle ^> ^ waitHandles, int millisecondsTimeout, bool exitContext);
public static int WaitAny (System.Threading.WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext);
static member WaitAny : System.Threading.WaitHandle[] * int * bool -> int
Public Shared Function WaitAny (waitHandles As WaitHandle(), millisecondsTimeout As Integer, exitContext As Boolean) As Integer

Параметры

waitHandles
WaitHandle[]

Массив WaitHandle, содержащий объекты, ожидаемые текущим экземпляром.

millisecondsTimeout
Int32

Время ожидания в миллисекундах или функция Infinite (-1) в случае неограниченного времени ожидания.

exitContext
Boolean

Значение true для выхода из домена синхронизации в текущем контексте перед ожиданием (в синхронизированном контексте) с его последующим повторным получением; в противном случае — false.

Возвращаемое значение

Индекс объекта в массиве, удовлетворившего условиям ожидания, или значение WaitTimeout, если ни один из объектов не удовлетворил условиям ожидания и истек интервал времени, равный millisecondsTimeout.

Исключения

Параметр waitHandles имеет значение null.

-или-

Один или несколько объектов массива waitHandles имеют значение null.

Массив waitHandles содержит больше объектов, чем разрешено системой.

waitHandles является массивом без элементов, а платформа .NET Framework имеет версию 1.0 или 1.1.

Параметр millisecondsTimeout является отрицательным числом, отличным от –1, что означает бесконечное время ожидания.

Ожидание закончилось, так как поток завершил работу, не освободив мьютекс.

waitHandles является массивом без элементов, а платформа .NET Framework имеет версию 2.0 или выше.

Массив waitHandles содержит прозрачный прокси для элемента WaitHandle в другом домене приложения.

Примеры

В следующем примере кода показано, как использовать пул потоков для одновременного поиска файла на нескольких дисках. При необходимости выполняется поиск только в корневом каталоге каждого диска.

using namespace System;
using namespace System::IO;
using namespace System::Threading;
ref class Search
{
private:

   // Maintain state information to pass to FindCallback.
   ref class State
   {
   public:
      AutoResetEvent^ autoEvent;
      String^ fileName;
      State( AutoResetEvent^ autoEvent, String^ fileName )
         : autoEvent( autoEvent ), fileName( fileName )
      {}

   };


public:
   array<AutoResetEvent^>^autoEvents;
   array<String^>^diskLetters;

   // Search for stateInfo->fileName.
   void FindCallback( Object^ state )
   {
      State^ stateInfo = dynamic_cast<State^>(state);
      
      // Signal if the file is found.
      if ( File::Exists( stateInfo->fileName ) )
      {
         stateInfo->autoEvent->Set();
      }
   }

   Search()
   {
      
      // Retrieve an array of disk letters.
      diskLetters = Environment::GetLogicalDrives();
      autoEvents = gcnew array<AutoResetEvent^>(diskLetters->Length);
      for ( int i = 0; i < diskLetters->Length; i++ )
      {
         autoEvents[ i ] = gcnew AutoResetEvent( false );

      }
   }


   // Search for fileName in the root directory of all disks.
   void FindFile( String^ fileName )
   {
      for ( int i = 0; i < diskLetters->Length; i++ )
      {
         Console::WriteLine(  "Searching for {0} on {1}.", fileName, diskLetters[ i ] );
         ThreadPool::QueueUserWorkItem( gcnew WaitCallback( this, &Search::FindCallback ), gcnew State( autoEvents[ i ],String::Concat( diskLetters[ i ], fileName ) ) );

      }
      
      // Wait for the first instance of the file to be found.
      int index = WaitHandle::WaitAny( autoEvents, 3000, false );
      if ( index == WaitHandle::WaitTimeout )
      {
         Console::WriteLine( "\n{0} not found.", fileName );
      }
      else
      {
         Console::WriteLine( "\n{0} found on {1}.", fileName, diskLetters[ index ] );
      }
   }

};

int main()
{
   Search^ search = gcnew Search;
   search->FindFile( "SomeFile.dat" );
}
using System;
using System.IO;
using System.Threading;

class Test
{
    static void Main()
    {
        Search search = new Search();
        search.FindFile("SomeFile.dat");
    }
}

class Search
{
    // Maintain state information to pass to FindCallback.
    class State
    {
        public AutoResetEvent autoEvent;
        public string         fileName;

        public State(AutoResetEvent autoEvent, string fileName)
        {
            this.autoEvent    = autoEvent;
            this.fileName     = fileName;
        }
    }

    AutoResetEvent[] autoEvents;
    String[] diskLetters;

    public Search()
    {
        // Retrieve an array of disk letters.
        diskLetters = Environment.GetLogicalDrives();

        autoEvents = new AutoResetEvent[diskLetters.Length];
        for(int i = 0; i < diskLetters.Length; i++)
        {
            autoEvents[i] = new AutoResetEvent(false);
        }
    }

    // Search for fileName in the root directory of all disks.
    public void FindFile(string fileName)
    {
        for(int i = 0; i < diskLetters.Length; i++)
        {
            Console.WriteLine("Searching for {0} on {1}.",
                fileName, diskLetters[i]);
            ThreadPool.QueueUserWorkItem(
                new WaitCallback(FindCallback), 
                new State(autoEvents[i], diskLetters[i] + fileName));
        }

        // Wait for the first instance of the file to be found.
        int index = WaitHandle.WaitAny(autoEvents, 3000, false);
        if(index == WaitHandle.WaitTimeout)
        {
            Console.WriteLine("\n{0} not found.", fileName);
        }
        else
        {
            Console.WriteLine("\n{0} found on {1}.", fileName,
                diskLetters[index]);
        }
    }

    // Search for stateInfo.fileName.
    void FindCallback(object state)
    {
        State stateInfo = (State)state;

        // Signal if the file is found.
        if(File.Exists(stateInfo.fileName))
        {
            stateInfo.autoEvent.Set();
        }
    }
}
Imports System.IO
Imports System.Threading

Public Class Test

    <MTAThread> _
    Shared Sub Main()
        Dim search As New Search()
        search.FindFile("SomeFile.dat")
    End Sub    
End Class

Public Class Search

    ' Maintain state information to pass to FindCallback.
    Class State
        Public autoEvent As AutoResetEvent 
        Public fileName As String         

        Sub New(anEvent As AutoResetEvent, fName As String)
            autoEvent = anEvent
            fileName = fName
        End Sub
    End Class

    Dim autoEvents() As AutoResetEvent
    Dim diskLetters() As String

    Sub New()

        ' Retrieve an array of disk letters.
        diskLetters = Environment.GetLogicalDrives()

        autoEvents = New AutoResetEvent(diskLetters.Length - 1) {}
        For i As Integer = 0 To diskLetters.Length - 1
            autoEvents(i) = New AutoResetEvent(False)
        Next i
    End Sub    
    
    ' Search for fileName in the root directory of all disks.
    Sub FindFile(fileName As String)
        For i As Integer = 0 To diskLetters.Length - 1
            Console.WriteLine("Searching for {0} on {1}.", _
                fileName, diskLetters(i))
        
            ThreadPool.QueueUserWorkItem(AddressOf FindCallback, _ 
                New State(autoEvents(i), diskLetters(i) & fileName))
        Next i

        ' Wait for the first instance of the file to be found.
        Dim index As Integer = _
            WaitHandle.WaitAny(autoEvents, 3000, False)
        If index = WaitHandle.WaitTimeout
            Console.WriteLine(vbCrLf & "{0} not found.", fileName)
        Else
            Console.WriteLine(vbCrLf & "{0} found on {1}.", _
                fileName, diskLetters(index))
        End If
    End Sub

    ' Search for stateInfo.fileName.
    Sub FindCallback(state As Object)
        Dim stateInfo As State = DirectCast(state, State)

        ' Signal if the file is found.
        If File.Exists(stateInfo.fileName) Then
            stateInfo.autoEvent.Set()
        End If
    End Sub

End Class

Комментарии

Если millisecondsTimeout равно нулю, метод не блокируется. Он проверяет состояние дескрипторов ожидания и возвращается немедленно.

AbandonedMutexExceptionявляется новым в платформа .NET Framework версии 2.0. В предыдущих версиях метод возвращает значение true , WaitAny если ожидание завершается из-за отказа от мьютекса. Отказ от мьютекса часто указывает на серьезную ошибку кодирования. В случае системного мьютекса это может означать, что приложение было внезапно завершено (например, с помощью диспетчера задач Windows). Исключение содержит сведения, полезные для отладки.

Метод WaitAny создает исключение AbandonedMutexException только после завершения ожидания из-за отказа от мьютекса. Если waitHandles содержит освобожденный мьютекс с более низким номером индекса, чем прерванный мьютекс, WaitAny метод завершается обычным образом и исключение не создается.

Примечание

В версиях платформа .NET Framework более ранней, чем версия 2.0, если поток завершается или прерывается без явного освобождения Mutexи Mutex имеет индекс 0 (нуль) в массиве в WaitAny другом потоке, индекс, возвращаемый методомWaitAny, равен 128, а не 0.

Этот метод возвращает значение, когда ожидание завершается, когда сигнализирует какой-либо из дескрипторов, или при истечении времени ожидания. Если во время вызова подается сигнал о нескольких объектах, возвращаемое значение представляет собой индекс массива сигнального объекта с наименьшим значением индекса из всех сигнальных объектов.

Максимальное число дескрипторов ожидания — 64 и 63, если текущий поток находится в STA состоянии.

Примечания о выходе из контекста

Параметр exitContext не действует, если WaitAny метод не вызывается из нестандартного управляемого контекста. Это может произойти, если поток находится внутри вызова экземпляра класса, производного от ContextBoundObject. Даже если в настоящее время выполняется метод в классе, который не является производным от ContextBoundObject, например String, вы можете находиться в контексте, не являющемся стандартным, если ContextBoundObject находится в стеке в текущем домене приложения.

При выполнении кода в контексте, не являющегося стандартным, указание true для exitContext приводит к выходу потока из неуправляемого контекста (т. е. для перехода в контекст по умолчанию) перед выполнением WaitAny метода . После завершения вызова метода поток возвращается в исходный WaitAny контекст nondefault.

Это может быть полезно, если контекстно-привязанный класс имеет .SynchronizationAttribute В этом случае все вызовы членов класса синхронизируются автоматически, а домен синхронизации — это весь текст кода для класса. Если код в стеке вызовов true члена вызывает WaitAny метод и указывает для exitContext, поток выходит из домена синхронизации, позволяя потоку, заблокированном при вызове любого члена объекта, продолжить работу. При возврате WaitAny метода поток, который сделал вызов, должен дождаться повторного входить в домен синхронизации.

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

WaitAny(WaitHandle[], TimeSpan, Boolean)

Ожидает получения сигнала какими-либо элементами заданного массива, используя TimeSpan для задания интервала времени и указывая, следует ли выйти из домена синхронизации до начала ожидания.

public:
 static int WaitAny(cli::array <System::Threading::WaitHandle ^> ^ waitHandles, TimeSpan timeout, bool exitContext);
public static int WaitAny (System.Threading.WaitHandle[] waitHandles, TimeSpan timeout, bool exitContext);
static member WaitAny : System.Threading.WaitHandle[] * TimeSpan * bool -> int
Public Shared Function WaitAny (waitHandles As WaitHandle(), timeout As TimeSpan, exitContext As Boolean) As Integer

Параметры

waitHandles
WaitHandle[]

Массив WaitHandle, содержащий объекты, ожидаемые текущим экземпляром.

timeout
TimeSpan

Период TimeSpan, представляющий время ожидания в миллисекундах, или период TimeSpan, представляющий -1 миллисекунду для неограниченного ожидания.

exitContext
Boolean

Значение true для выхода из домена синхронизации в текущем контексте перед ожиданием (в синхронизированном контексте) с его последующим повторным получением; в противном случае — false.

Возвращаемое значение

Индекс объекта в массиве, удовлетворившего условиям ожидания, или значение WaitTimeout, если ни один из объектов не удовлетворил условиям ожидания и истек интервал времени, равный timeout.

Исключения

Параметр waitHandles имеет значение null.

-или-

Один или несколько объектов массива waitHandles имеют значение null.

Массив waitHandles содержит больше объектов, чем разрешено системой.

waitHandles является массивом без элементов, а платформа .NET Framework имеет версию 1.0 или 1.1.

timeout является отрицательным числом, отличным от -1 миллисекунды, которое представляет неограниченное время ожидания.

-или-

timeout больше, чем Int32.MaxValue.

Ожидание закончилось, так как поток завершил работу, не освободив мьютекс.

waitHandles является массивом без элементов, а платформа .NET Framework имеет версию 2.0 или выше.

Массив waitHandles содержит прозрачный прокси для элемента WaitHandle в другом домене приложения.

Примеры

В следующем примере кода показано, как использовать пул потоков для одновременного поиска файла на нескольких дисках. При необходимости выполняется поиск только в корневом каталоге каждого диска.

using namespace System;
using namespace System::IO;
using namespace System::Threading;
ref class Search
{
private:

   // Maintain state information to pass to FindCallback.
   ref class State
   {
   public:
      AutoResetEvent^ autoEvent;
      String^ fileName;
      State( AutoResetEvent^ autoEvent, String^ fileName )
         : autoEvent( autoEvent ), fileName( fileName )
      {}

   };


public:
   array<AutoResetEvent^>^autoEvents;
   array<String^>^diskLetters;

   // Search for stateInfo->fileName.
   void FindCallback( Object^ state )
   {
      State^ stateInfo = dynamic_cast<State^>(state);
      
      // Signal if the file is found.
      if ( File::Exists( stateInfo->fileName ) )
      {
         stateInfo->autoEvent->Set();
      }
   }

   Search()
   {
      
      // Retrieve an array of disk letters.
      diskLetters = Environment::GetLogicalDrives();
      autoEvents = gcnew array<AutoResetEvent^>(diskLetters->Length);
      for ( int i = 0; i < diskLetters->Length; i++ )
      {
         autoEvents[ i ] = gcnew AutoResetEvent( false );

      }
   }


   // Search for fileName in the root directory of all disks.
   void FindFile( String^ fileName )
   {
      for ( int i = 0; i < diskLetters->Length; i++ )
      {
         Console::WriteLine(  "Searching for {0} on {1}.", fileName, diskLetters[ i ] );
         ThreadPool::QueueUserWorkItem( gcnew WaitCallback( this, &Search::FindCallback ), gcnew State( autoEvents[ i ],String::Concat( diskLetters[ i ], fileName ) ) );

      }
      
      // Wait for the first instance of the file to be found.
      int index = WaitHandle::WaitAny( autoEvents, TimeSpan(0,0,3), false );
      if ( index == WaitHandle::WaitTimeout )
      {
         Console::WriteLine( "\n{0} not found.", fileName );
      }
      else
      {
         Console::WriteLine( "\n{0} found on {1}.", fileName, diskLetters[ index ] );
      }
   }

};

int main()
{
   Search^ search = gcnew Search;
   search->FindFile( "SomeFile.dat" );
}
using System;
using System.IO;
using System.Threading;

class Test
{
    static void Main()
    {
        Search search = new Search();
        search.FindFile("SomeFile.dat");
    }
}

class Search
{
    // Maintain state information to pass to FindCallback.
    class State
    {
        public AutoResetEvent autoEvent;
        public string         fileName;

        public State(AutoResetEvent autoEvent, string fileName)
        {
            this.autoEvent    = autoEvent;
            this.fileName     = fileName;
        }
    }

    AutoResetEvent[] autoEvents;
    String[] diskLetters;

    public Search()
    {
        // Retrieve an array of disk letters.
        diskLetters = Environment.GetLogicalDrives();

        autoEvents = new AutoResetEvent[diskLetters.Length];
        for(int i = 0; i < diskLetters.Length; i++)
        {
            autoEvents[i] = new AutoResetEvent(false);
        }
    }

    // Search for fileName in the root directory of all disks.
    public void FindFile(string fileName)
    {
        for(int i = 0; i < diskLetters.Length; i++)
        {
            Console.WriteLine("Searching for {0} on {1}.",
                fileName, diskLetters[i]);
            ThreadPool.QueueUserWorkItem(
                new WaitCallback(FindCallback), 
                new State(autoEvents[i], diskLetters[i] + fileName));
        }

        // Wait for the first instance of the file to be found.
        int index = WaitHandle.WaitAny(
            autoEvents, new TimeSpan(0, 0, 3), false);
        if(index == WaitHandle.WaitTimeout)
        {
            Console.WriteLine("\n{0} not found.", fileName);
        }
        else
        {
            Console.WriteLine("\n{0} found on {1}.", fileName,
                diskLetters[index]);
        }
    }

    // Search for stateInfo.fileName.
    void FindCallback(object state)
    {
        State stateInfo = (State)state;

        // Signal if the file is found.
        if(File.Exists(stateInfo.fileName))
        {
            stateInfo.autoEvent.Set();
        }
    }
}
Imports System.IO
Imports System.Threading

Public Class Test

    <MTAThread> _
    Shared Sub Main()
        Dim search As New Search()
        search.FindFile("SomeFile.dat")
    End Sub    
End Class

Public Class Search

    ' Maintain state information to pass to FindCallback.
    Class State
        Public autoEvent As AutoResetEvent 
        Public fileName As String         

        Sub New(anEvent As AutoResetEvent, fName As String)
            autoEvent = anEvent
            fileName = fName
        End Sub
    End Class

    Dim autoEvents() As AutoResetEvent
    Dim diskLetters() As String

    Sub New()

        ' Retrieve an array of disk letters.
        diskLetters = Environment.GetLogicalDrives()

        autoEvents = New AutoResetEvent(diskLetters.Length - 1) {}
        For i As Integer = 0 To diskLetters.Length - 1
            autoEvents(i) = New AutoResetEvent(False)
        Next i
    End Sub    
    
    ' Search for fileName in the root directory of all disks.
    Sub FindFile(fileName As String)
        For i As Integer = 0 To diskLetters.Length - 1
            Console.WriteLine("Searching for {0} on {1}.", _
                fileName, diskLetters(i))
        
            ThreadPool.QueueUserWorkItem(AddressOf FindCallback, _ 
                New State(autoEvents(i), diskLetters(i) & fileName))
        Next i

        ' Wait for the first instance of the file to be found.
        Dim index As Integer = WaitHandle.WaitAny( _
            autoEvents, New TimeSpan(0, 0, 3), False)
        If index = WaitHandle.WaitTimeout
            Console.WriteLine(vbCrLf & "{0} not found.", fileName)
        Else
            Console.WriteLine(vbCrLf & "{0} found on {1}.", _
                fileName, diskLetters(index))
        End If
    End Sub

    ' Search for stateInfo.fileName.
    Sub FindCallback(state As Object)
        Dim stateInfo As State = DirectCast(state, State)

        ' Signal if the file is found.
        If File.Exists(stateInfo.fileName) Then
            stateInfo.autoEvent.Set()
        End If
    End Sub

End Class

Комментарии

Если timeout равно нулю, метод не блокируется. Он проверяет состояние дескрипторов ожидания и возвращается немедленно.

AbandonedMutexExceptionявляется новым в платформа .NET Framework версии 2.0. В предыдущих версиях метод возвращает значение true , WaitAny если ожидание завершается из-за отказа от мьютекса. Отказ от мьютекса часто указывает на серьезную ошибку кодирования. В случае системного мьютекса это может означать, что приложение было внезапно завершено (например, с помощью диспетчера задач Windows). Исключение содержит сведения, полезные для отладки.

Метод WaitAny создает исключение AbandonedMutexException только после завершения ожидания из-за отказа от мьютекса. Если waitHandles содержит освобожденный мьютекс с более низким номером индекса, чем прерванный мьютекс, WaitAny метод завершается обычным образом и исключение не создается.

Примечание

В версиях платформа .NET Framework более ранней, чем версия 2.0, если поток завершается или прерывается без явного освобождения Mutexи Mutex имеет индекс 0 (нуль) в массиве в WaitAny другом потоке, индекс, возвращаемый методомWaitAny, равен 128, а не 0.

Этот метод возвращает значение, когда ожидание завершается, когда сигнализирует какой-либо из дескрипторов, или при истечении времени ожидания. Если во время вызова подается сигнал о нескольких объектах, возвращаемое значение представляет собой индекс массива сигнального объекта с наименьшим значением индекса из всех сигнальных объектов.

Максимальное число дескрипторов ожидания — 64 и 63, если текущий поток находится в STA состоянии.

Максимальное значение для timeoutInt32.MaxValue.

Примечания о выходе из контекста

Параметр exitContext не действует, если WaitAny метод не вызывается из нестандартного управляемого контекста. Это может произойти, если поток находится внутри вызова экземпляра класса, производного от ContextBoundObject. Даже если в настоящее время выполняется метод в классе, который не является производным от ContextBoundObject, например String, вы можете находиться в контексте, не являющемся стандартным, если ContextBoundObject находится в стеке в текущем домене приложения.

При выполнении кода в контексте, не являющегося стандартным, указание true для exitContext приводит к выходу потока из неуправляемого контекста (т. е. для перехода в контекст по умолчанию) перед выполнением WaitAny метода . После завершения вызова метода поток возвращается в исходный WaitAny контекст nondefault.

Это может быть полезно, если контекстно-привязанный класс имеет .SynchronizationAttribute В этом случае все вызовы членов класса синхронизируются автоматически, а домен синхронизации — это весь текст кода для класса. Если код в стеке вызовов true члена вызывает WaitAny метод и указывает для exitContext, поток выходит из домена синхронизации, позволяя потоку, заблокированном при вызове любого члена объекта, продолжить работу. При возврате WaitAny метода поток, который сделал вызов, должен дождаться повторного входить в домен синхронизации.

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