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 数组,其中包含当前实例将等待的对象。

返回

满足等待的对象数组索引。

例外

参数 waitHandlesnull.

-或-

数组中的 waitHandles 一个或多个对象是 null

中的 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 将正常完成,并且不会引发异常。

注释

在低于版本 2.0 的 .NET Framework 版本中, 如果线程退出或中止而不显式释放 Mutex,并且 Mutex在另一个线程上的 WaitAny 数组中的索引为 0(零),则由 WaitAny 返回的索引为 128 而不是 0。

此方法在发出任何句柄信号时返回。 如果在调用期间收到多个对象的信号,则返回值是信号对象的数组索引,其索引值为所有信号对象中最小的索引值。

等待句柄的最大数目为 64,如果当前线程处于 STA 状态,则为 63。

调用此方法重载等效于调用WaitAny(WaitHandle[], Int32, Boolean)方法重载并为其指定 -1 (或Timeout.InfinitemillisecondsTimeouttrueexitContext

适用于

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 的时间间隔。

例外

参数 waitHandlesnull.

-或-

数组中的 waitHandles 一个或多个对象是 null

中的 waitHandles 对象数大于系统允许的数目。

millisecondsTimeout 是非 -1 的负数,表示无限超时。

等待已完成,因为线程退出而不释放互斥体。

waitHandles 是一个没有元素的数组。

waitHandles 数组包含另一个应用程序域中的 WaitHandle 透明代理。

注解

如果 millisecondsTimeout 为零,则该方法不会阻止。 它测试等待句柄的状态并立即返回。

WaitAny 当等待完成时,该方法才会因为放弃的互斥体而引发 AbandonedMutexException 。 如果 waitHandles 包含索引号低于放弃的互斥体的释放互斥体,该方法 WaitAny 将正常完成,并且不会引发异常。

此方法在等待终止时返回,当发出任何句柄信号或发生超时时返回。 如果在调用期间收到多个对象的信号,则返回值是信号对象的数组索引,其索引值为所有信号对象中最小的索引值。

等待句柄的最大数目为 64,如果当前线程处于 STA 状态,则为 63。

调用此方法重载与调用WaitAny(WaitHandle[], Int32, Boolean)重载和指定falseexitContext重载相同。

适用于

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 的时间间隔。

例外

参数 waitHandlesnull.

-或-

数组中的 waitHandles 一个或多个对象是 null

中的 waitHandles 对象数大于系统允许的数目。

timeout 是一个负数,而不是 -1 毫秒,表示无限超时。

-或-

timeout 大于 Int32.MaxValue

等待已完成,因为线程退出而不释放互斥体。

waitHandles 是一个没有元素的数组。

waitHandles 数组包含另一个应用程序域中的 WaitHandle 透明代理。

注解

如果 timeout 为零,则该方法不会阻止。 它测试等待句柄的状态并立即返回。

WaitAny 当等待完成时,该方法才会因为放弃的互斥体而引发 AbandonedMutexException 。 如果 waitHandles 包含索引号低于放弃的互斥体的释放互斥体,该方法 WaitAny 将正常完成,并且不会引发异常。

此方法在等待终止时返回,无论何时发出任何句柄的信号或发生超时。 如果在调用期间收到多个对象的信号,则返回值是信号对象的数组索引,其索引值为所有信号对象中最小的索引值。

等待句柄的最大数目为 64,如果当前线程处于 STA 状态,则为 63。

的最大值 timeoutInt32.MaxValue.

调用此方法重载与调用WaitAny(WaitHandle[], TimeSpan, Boolean)重载和指定falseexitContext重载相同。

适用于

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 的时间间隔。

例外

参数 waitHandlesnull.

-或-

数组中的 waitHandles 一个或多个对象是 null

中的 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,如果当前线程处于 STA 状态,则为 63。

退出上下文

除非从非默认托管上下文内部调用此方法,否则参数 exitContext 不起作用。 如果线程在对派生自 ContextBoundObject的类实例的调用中,则托管上下文可以是非默认上下文。 即使当前在未派生自 ContextBoundObject的类上执行方法,例如 String,如果在 ContextBoundObject 当前应用程序域中的堆栈上,也可以位于非默认上下文中。

当代码在非默认上下文中执行时,指定 trueexitContext 会导致线程在执行此方法之前退出非默认托管上下文(即转换到默认上下文)。 调用此方法后,线程将返回到原始非默认上下文。

当上下文绑定类具有 SynchronizationAttribute 属性时,退出上下文可能很有用。 在这种情况下,对类成员的所有调用都会自动同步,并且同步域是该类的整个代码正文。 如果成员调用堆栈中的代码调用此方法并指定 trueexitContext则线程将退出同步域,从而允许在调用对象的任何成员时阻止的线程继续。 此方法返回时,发出调用的线程必须等待重新输入同步域。

适用于

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 的时间间隔。

例外

参数 waitHandlesnull.

-或-

数组中的 waitHandles 一个或多个对象是 null

中的 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,如果当前线程处于 STA 状态,则为 63。

的最大值 timeoutInt32.MaxValue.

退出上下文

除非从非默认托管上下文内部调用此方法,否则参数 exitContext 不起作用。 如果线程在对派生自 ContextBoundObject的类实例的调用中,则托管上下文可以是非默认上下文。 即使当前在未派生自 ContextBoundObject的类上执行方法,例如 String,如果在 ContextBoundObject 当前应用程序域中的堆栈上,也可以位于非默认上下文中。

当代码在非默认上下文中执行时,指定 trueexitContext 会导致线程在执行此方法之前退出非默认托管上下文(即转换到默认上下文)。 调用此方法后,线程将返回到原始非默认上下文。

当上下文绑定类具有 SynchronizationAttribute 属性时,退出上下文可能很有用。 在这种情况下,对类成员的所有调用都会自动同步,并且同步域是该类的整个代码正文。 如果成员调用堆栈中的代码调用此方法并指定 trueexitContext则线程将退出同步域,从而允许在调用对象的任何成员时阻止的线程继续。 此方法返回时,发出调用的线程必须等待重新输入同步域。

适用于