WaitHandle 类

定义

封装等待对共享资源进行独占访问的操作系统特定的对象。

public ref class WaitHandle abstract : IDisposable
public ref class WaitHandle abstract : MarshalByRefObject, IDisposable
public abstract class WaitHandle : IDisposable
public abstract class WaitHandle : MarshalByRefObject, IDisposable
[System.Runtime.InteropServices.ComVisible(true)]
public abstract class WaitHandle : MarshalByRefObject, IDisposable
type WaitHandle = class
    interface IDisposable
type WaitHandle = class
    inherit MarshalByRefObject
    interface IDisposable
[<System.Runtime.InteropServices.ComVisible(true)>]
type WaitHandle = class
    inherit MarshalByRefObject
    interface IDisposable
Public MustInherit Class WaitHandle
Implements IDisposable
Public MustInherit Class WaitHandle
Inherits MarshalByRefObject
Implements IDisposable
继承
WaitHandle
继承
派生
属性
实现

示例

下面的代码示例演示两个线程如何使用 类的WaitHandle静态 WaitAnyWaitAll 方法在主线程等待任务完成时执行后台任务。

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).

注解

WaitHandle 封装本机操作系统同步句柄,并用于表示运行时中允许多个等待操作的所有同步对象。 有关等待句柄与其他同步对象的比较,请参阅 同步基元概述

WaitHandle 本身是抽象的。 派生自 WaitHandle 的类定义信号机制以指示获取或释放对共享资源的访问权限,但它们在等待访问共享资源时使用继承 WaitHandle 的方法阻止。 派生自 WaitHandle 的类包括:

线程可以通过调用 实例方法 WaitOne(由派生自 WaitHandle的类继承)来阻塞单个等待句柄。

WaitHandle 派生类的线程相关性不同。 事件等待句柄 (EventWaitHandleAutoResetEventManualResetEvent) 和信号灯没有线程关联;任何线程都可以发出事件等待句柄或信号灯的信号。 另一方面,互斥体确实具有线程相关性;拥有互斥体的线程必须释放它,如果线程对其不拥有的互斥体调用 ReleaseMutex 方法,则会引发异常。

WaitHandle由于 类派生自 MarshalByRefObject,因此这些类可用于跨应用程序域边界同步线程的活动。

除了派生类之外, WaitHandle 类还具有许多静态方法,这些方法会阻止线程,直到一个或多个同步对象收到信号。 这些方法包括:

  • SignalAndWait,它允许线程向一个等待句柄发出信号,并立即在另一个等待句柄上等待。

  • WaitAll,它允许线程等待数组中的所有等待句柄收到信号。

  • WaitAny,它允许线程等待,直到指定一组等待句柄中的任何一个被发出信号。

这些方法的重载提供放弃等待的超时间隔,以及进入等待前退出同步上下文的机会,从而允许其他线程使用同步上下文。

重要

此类型实现 IDisposable 接口。 使用完类型或派生自该类型的类型后,应直接或间接释放它。 若要直接释放类型,请在 try/catch 块中调用其 Close 方法。 若要间接释放类型,请使用 using(在 C# 中)或 Using(在 Visual Basic 中)等语言构造。 有关详细信息,请参阅 IDisposable 接口主题中的“使用实现 IDisposable 的对象”一节。

WaitHandle 实现 Dispose 模式。 请参阅 实现 Dispose 方法。 从 WaitHandle派生时, SafeWaitHandle 使用 属性存储本机操作系统句柄。 除非使用其他非托管资源,否则不需要重写受保护的 Dispose 方法。

构造函数

WaitHandle()

初始化 WaitHandle 类的新实例。

字段

InvalidHandle

表示无效的本机操作系统句柄。 此字段为只读。

WaitTimeout

指示在任何等待句柄终止之前 WaitAny(WaitHandle[], Int32, Boolean) 操作已超时。 此字段为常数。

属性

Handle
已过时.
已过时.

获取或设置本机操作系统句柄。

SafeWaitHandle

获取或设置本机操作系统句柄。

方法

Close()

释放由当前 WaitHandle 占用的所有资源。

CreateObjRef(Type)

创建一个对象,该对象包含生成用于与远程对象进行通信的代理所需的全部相关信息。

(继承自 MarshalByRefObject)
Dispose()

释放 WaitHandle 类的当前实例所使用的所有资源。

Dispose(Boolean)

当在派生类中重写时,释放 WaitHandle 使用的非托管资源,并且可选择释放托管资源。

Equals(Object)

确定指定对象是否等于当前对象。

(继承自 Object)
Finalize()

释放由当前实例所持有的资源。

GetHashCode()

作为默认哈希函数。

(继承自 Object)
GetLifetimeService()
已过时.

检索控制此实例的生存期策略的当前生存期服务对象。

(继承自 MarshalByRefObject)
GetType()

获取当前实例的 Type

(继承自 Object)
InitializeLifetimeService()
已过时.

获取生存期服务对象来控制此实例的生存期策略。

(继承自 MarshalByRefObject)
MemberwiseClone()

创建当前 Object 的浅表副本。

(继承自 Object)
MemberwiseClone(Boolean)

创建当前 MarshalByRefObject 对象的浅表副本。

(继承自 MarshalByRefObject)
SignalAndWait(WaitHandle, WaitHandle)

向一个 WaitHandle 发出信号并等待另一个。

SignalAndWait(WaitHandle, WaitHandle, Int32, Boolean)

向一个 WaitHandle 发出信号并等待另一个,指定超时间隔为 32 位有符号整数,并指定在进入等待前是否退出上下文的同步域。

SignalAndWait(WaitHandle, WaitHandle, TimeSpan, Boolean)

向一个 WaitHandle 发出信号并等待另一个,指定超时间隔为 TimeSpan,并指定在进入等待前是否退出上下文的同步域。

ToString()

返回表示当前对象的字符串。

(继承自 Object)
WaitAll(WaitHandle[])

等待指定数组中的所有元素都收到信号。

WaitAll(WaitHandle[], Int32)

等待指定数组中的所有元素接收信号,同时使用 Int32 值指定时间间隔。

WaitAll(WaitHandle[], Int32, Boolean)

等待指定数组中的所有元素收到信号,使用 Int32 值指定时间间隔,并指定是否在等待之前退出同步域。

WaitAll(WaitHandle[], TimeSpan)

等待指定数组中的所有元素接收信号,同时使用 TimeSpan 值指定时间间隔。

WaitAll(WaitHandle[], TimeSpan, Boolean)

等待指定数组中的所有元素收到信号,使用 TimeSpan 值指定时间间隔,并指定是否在等待之前退出同步域。

WaitAny(WaitHandle[])

等待指定数组中的任一元素收到信号。

WaitAny(WaitHandle[], Int32)

等待指定数组中的任意元素接收信号,同时使用 32 位有符号整数指定时间间隔。

WaitAny(WaitHandle[], Int32, Boolean)

等待指定数组中的任一元素收到信号,使用 32 位带符号整数指定时间间隔并指定是否在等待之前退出同步域。

WaitAny(WaitHandle[], TimeSpan)

等待指定数组中的任意元素接收信号,同时使用 TimeSpan 指定时间间隔。

WaitAny(WaitHandle[], TimeSpan, Boolean)

等待指定数组中的任一元素收到信号,使用 TimeSpan 指定时间间隔并指定是否在等待之前退出同步域。

WaitOne()

阻止当前线程,直到当前 WaitHandle 收到信号。

WaitOne(Int32)

阻止当前线程,直到当前 WaitHandle 收到信号,同时使用 32 位带符号整数指定时间间隔(以毫秒为单位)。

WaitOne(Int32, Boolean)

阻止当前线程,直到当前的 WaitHandle 收到信号为止,同时使用 32 位带符号整数指定时间间隔,并指定是否在等待之前退出同步域。

WaitOne(TimeSpan)

阻止当前线程,直到当前实例收到信号,同时使用 TimeSpan 指定时间间隔。

WaitOne(TimeSpan, Boolean)

阻止当前线程,直到当前实例收到信号为止,同时使用 TimeSpan 指定时间间隔,并指定是否在等待之前退出同步域。

显式接口实现

IDisposable.Dispose()

此 API 支持产品基础结构,不能在代码中直接使用。

释放由 WaitHandle 使用的所有资源。

扩展方法

GetSafeWaitHandle(WaitHandle)

获取本机操作系统等待句柄的安全句柄。

SetSafeWaitHandle(WaitHandle, SafeWaitHandle)

设置本机操作系统等待句柄的安全句柄。

适用于

线程安全性

此类型是线程安全的。

另请参阅