WaitHandle.WaitAny Метод

Определение

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

Перегрузки

Имя Описание
WaitAny(WaitHandle[])

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

WaitAny(WaitHandle[], Int32)

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

WaitAny(WaitHandle[], TimeSpan)

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

WaitAny(WaitHandle[], Int32, Boolean)

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

WaitAny(WaitHandle[], TimeSpan, Boolean)

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

WaitAny(WaitHandle[])

Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs

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

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.

–или–

Один или несколько объектов в массиве waitHandlesnull.

Число объектов больше waitHandles , чем разрешение системы.

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

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

waitHandles — это массив без элементов, а версия .NET Framework — 2.0 или более поздней.

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

Примеры

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

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. В предыдущих версиях метод возвращаетсяWaitAny, если ожидание завершается, true так как мьютекс отказывается. Заброшенный мьютекс часто указывает на серьезную ошибку кодирования. В случае с мьютексом на уровне системы может быть указано, что приложение было внезапно завершено (например, с помощью диспетчера задач Windows). Исключение содержит сведения, полезные для отладки.

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

Note

В версиях платформы .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)

Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs

Ожидает, чтобы любой из элементов в указанном массиве получил сигнал, используя 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.

–или–

Один или несколько объектов в массиве waitHandlesnull.

Число объектов больше waitHandles , чем разрешение системы.

millisecondsTimeout — отрицательное число, отличное от -1, которое представляет бесконечное время ожидания.

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

waitHandles — это массив без элементов.

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

Комментарии

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

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

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

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

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

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

WaitAny(WaitHandle[], TimeSpan)

Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs

Ожидает, пока любой из элементов в указанном массиве получит сигнал, используя 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.

–или–

Один или несколько объектов в массиве waitHandlesnull.

Число объектов больше 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)

Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs

Ожидает, пока любой из элементов в указанном массиве получит сигнал, используя 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.

–или–

Один или несколько объектов в массиве waitHandlesnull.

Число объектов больше waitHandles , чем разрешение системы.

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

millisecondsTimeout — отрицательное число, отличное от -1, которое представляет бесконечное время ожидания.

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

waitHandles — это массив без элементов, а версия .NET Framework — 2.0 или более поздней.

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

Примеры

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

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

Метод WaitAny создает исключение AbandonedMutexException только после завершения ожидания из-за заброшенного мьютекса. Если waitHandles содержит выпущенный мьютекс с меньшим числом индекса, чем заброшенный мьютекс, метод завершается нормально, WaitAny и исключение не создается. Заброшенный мьютекс часто указывает на серьезную ошибку кодирования. В случае с мьютексом на уровне системы может быть указано, что приложение было внезапно завершено (например, с помощью диспетчера задач Windows). Исключение содержит сведения, полезные для отладки.

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

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

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

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

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

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

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

WaitAny(WaitHandle[], TimeSpan, Boolean)

Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs
Исходный код:
WaitHandle.cs

Ожидает, чтобы любой из элементов в указанном массиве получил сигнал, используя 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.

–или–

Один или несколько объектов в массиве waitHandlesnull.

Число объектов больше waitHandles , чем разрешение системы.

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

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

–или–

timeout больше int32.MaxValue.

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

waitHandles — это массив без элементов, а версия .NET Framework — 2.0 или более поздней.

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

Примеры

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

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

Метод WaitAny создает исключение AbandonedMutexException только после завершения ожидания из-за заброшенного мьютекса. Если waitHandles содержит выпущенный мьютекс с меньшим числом индекса, чем заброшенный мьютекс, метод завершается нормально, WaitAny и исключение не создается. Заброшенный мьютекс часто указывает на серьезную ошибку кодирования. В случае с мьютексом на уровне системы может быть указано, что приложение было внезапно завершено (например, с помощью диспетчера задач Windows). Исключение содержит сведения, полезные для отладки.

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

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

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

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

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

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

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

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