ManualResetEventSlim 类

定义

表示必须手动重置信号的线程同步事件。 此类是一种轻型替代方法 ManualResetEvent

public ref class ManualResetEventSlim : IDisposable
public class ManualResetEventSlim : IDisposable
[System.Runtime.InteropServices.ComVisible(false)]
public class ManualResetEventSlim : IDisposable
type ManualResetEventSlim = class
    interface IDisposable
[<System.Runtime.InteropServices.ComVisible(false)>]
type ManualResetEventSlim = class
    interface IDisposable
Public Class ManualResetEventSlim
Implements IDisposable
继承
ManualResetEventSlim
属性
实现

示例

以下示例演示如何使用 ManualResetEventSlim.

using System;
using System.Threading;
using System.Threading.Tasks;
class MRESDemo
{

    static void Main()
    {
        MRES_SetWaitReset();
        MRES_SpinCountWaitHandle();
    }
    // Demonstrates:
    //      ManualResetEventSlim construction
    //      ManualResetEventSlim.Wait()
    //      ManualResetEventSlim.Set()
    //      ManualResetEventSlim.Reset()
    //      ManualResetEventSlim.IsSet
    static void MRES_SetWaitReset()
    {
        ManualResetEventSlim mres1 = new ManualResetEventSlim(false); // initialize as unsignaled
        ManualResetEventSlim mres2 = new ManualResetEventSlim(false); // initialize as unsignaled
        ManualResetEventSlim mres3 = new ManualResetEventSlim(true);  // initialize as signaled

        // Start an asynchronous Task that manipulates mres3 and mres2
        var observer = Task.Factory.StartNew(() =>
        {
            mres1.Wait();
            Console.WriteLine("observer sees signaled mres1!");
            Console.WriteLine("observer resetting mres3...");
            mres3.Reset(); // should switch to unsignaled
            Console.WriteLine("observer signalling mres2");
            mres2.Set();
        });

        Console.WriteLine("main thread: mres3.IsSet = {0} (should be true)", mres3.IsSet);
        Console.WriteLine("main thread signalling mres1");
        mres1.Set(); // This will "kick off" the observer Task
        mres2.Wait(); // This won't return until observer Task has finished resetting mres3
        Console.WriteLine("main thread sees signaled mres2!");
        Console.WriteLine("main thread: mres3.IsSet = {0} (should be false)", mres3.IsSet);

        // It's good form to Dispose() a ManualResetEventSlim when you're done with it
        observer.Wait(); // make sure that this has fully completed
        mres1.Dispose();
        mres2.Dispose();
        mres3.Dispose();
    }

    // Demonstrates:
    //      ManualResetEventSlim construction w/ SpinCount
    //      ManualResetEventSlim.WaitHandle
    static void MRES_SpinCountWaitHandle()
    {
        // Construct a ManualResetEventSlim with a SpinCount of 1000
        // Higher spincount => longer time the MRES will spin-wait before taking lock
        ManualResetEventSlim mres1 = new ManualResetEventSlim(false, 1000);
        ManualResetEventSlim mres2 = new ManualResetEventSlim(false, 1000);

        Task bgTask = Task.Factory.StartNew(() =>
        {
            // Just wait a little
            Thread.Sleep(100);

            // Now signal both MRESes
            Console.WriteLine("Task signalling both MRESes");
            mres1.Set();
            mres2.Set();
        });

        // A common use of MRES.WaitHandle is to use MRES as a participant in 
        // WaitHandle.WaitAll/WaitAny.  Note that accessing MRES.WaitHandle will
        // result in the unconditional inflation of the underlying ManualResetEvent.
        WaitHandle.WaitAll(new WaitHandle[] { mres1.WaitHandle, mres2.WaitHandle });
        Console.WriteLine("WaitHandle.WaitAll(mres1.WaitHandle, mres2.WaitHandle) completed.");

        // Clean up
        bgTask.Wait();
        mres1.Dispose();
        mres2.Dispose();
    }
}
Imports System.Threading
Imports System.Threading.Tasks

Module MRESDemo

    Sub Main()

    End Sub
    ' Demonstrates:
    ' ManualResetEventSlim construction
    ' ManualResetEventSlim.Wait()
    ' ManualResetEventSlim.Set()
    ' ManualResetEventSlim.Reset()
    ' ManualResetEventSlim.IsSet
    Private Sub MRES_SetWaitReset()
        ' initialize as unsignaled
        Dim mres1 As New ManualResetEventSlim(False)
        ' initialize as unsignaled
        Dim mres2 As New ManualResetEventSlim(False)
        ' initialize as signaled
        Dim mres3 As New ManualResetEventSlim(True)

        ' Start an asynchronous Task that manipulates mres3 and mres2
        Dim observer = Task.Factory.StartNew(
            Sub()
                mres1.Wait()
                Console.WriteLine("observer sees signaled mres1!")
                Console.WriteLine("observer resetting mres3...")
                mres3.Reset()
                ' should switch to unsignaled
                Console.WriteLine("observer signalling mres2")
                mres2.[Set]()
            End Sub)

        Console.WriteLine("main thread: mres3.IsSet = {0} (should be true)", mres3.IsSet)
        Console.WriteLine("main thread signalling mres1")
        mres1.[Set]()
        ' This will "kick off" the observer Task
        mres2.Wait()
        ' This won't return until observer Task has finished resetting mres3
        Console.WriteLine("main thread sees signaled mres2!")
        Console.WriteLine("main thread: mres3.IsSet = {0} (should be false)", mres3.IsSet)

        ' make sure that observer has fully completed
        observer.Wait()
        ' It's good form to Dispose() a ManualResetEventSlim when you're done with it
        mres1.Dispose()
        mres2.Dispose()
        mres3.Dispose()
    End Sub

    ' Demonstrates:
    ' ManualResetEventSlim construction w/ SpinCount
    ' ManualResetEventSlim.WaitHandle
    Private Sub MRES_SpinCountWaitHandle()
        ' Construct a ManualResetEventSlim with a SpinCount of 1000
        ' Higher spincount => longer time the MRES will spin-wait before taking lock
        Dim mres1 As New ManualResetEventSlim(False, 1000)
        Dim mres2 As New ManualResetEventSlim(False, 1000)

        Dim bgTask As Task = Task.Factory.StartNew(
            Sub()
                ' Just wait a little
                Thread.Sleep(100)

                ' Now signal both MRESes
                Console.WriteLine("Task signalling both MRESes")
                mres1.[Set]()
                mres2.[Set]()
            End Sub)

        ' A common use of MRES.WaitHandle is to use MRES as a participant in 
        ' WaitHandle.WaitAll/WaitAny. Note that accessing MRES.WaitHandle will
        ' result in the unconditional inflation of the underlying ManualResetEvent.
        WaitHandle.WaitAll(New WaitHandle() {mres1.WaitHandle, mres2.WaitHandle})
        Console.WriteLine("WaitHandle.WaitAll(mres1.WaitHandle, mres2.WaitHandle) completed.")

        ' Wait for bgTask to complete and clean up
        bgTask.Wait()
        mres1.Dispose()
        mres2.Dispose()
    End Sub
End Module

注解

可以将此类用于比预期等待时间非常短且事件未越过进程边界时更好的性能 ManualResetEventManualResetEventSlim 在等待事件发出信号时,使用忙碌的旋转时间很短。 当等待时间较短时,旋转的成本可能比使用等待句柄要低得多。 但是,如果事件未在特定时间段内发出信号, ManualResetEventSlim 则表示定期事件句柄等待。

注意

在 .NET Core 和 .NET 5+中,默认旋转等待持续时间较短:根据平台和处理器,以 10 秒为单位的顺序。 如果预计等待时间比这长得多,你仍然可以使用此类,而不是 ManualResetEvent (可能配置为更少或没有旋转等待)。 但是,性能优势可能只是边际优势。

构造函数

名称 说明
ManualResetEventSlim()

使用非对齐的初始状态初始化类的新实例 ManualResetEventSlim

ManualResetEventSlim(Boolean, Int32)

使用布尔值初始化类的新实例 ManualResetEventSlim ,该值指示是否将初始状态设置为信号和指定的旋转计数。

ManualResetEventSlim(Boolean)

使用布尔值初始化类的新实例 ManualResetEventSlim ,该值指示是否将初始状态设置为信号。

属性

名称 说明
IsSet

获取是否设置事件。

SpinCount

获取在回退到基于内核的等待操作之前将发生的旋转等待数。

WaitHandle

获取此ManualResetEventSlim对象的基础WaitHandle对象。

方法

名称 说明
Dispose()

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

Dispose(Boolean)

释放由该资源使用 ManualResetEventSlim的非托管资源,并选择性地释放托管资源。

Equals(Object)

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

(继承自 Object)
GetHashCode()

用作默认哈希函数。

(继承自 Object)
GetType()

获取当前实例的 Type

(继承自 Object)
MemberwiseClone()

创建当前 Object的浅表副本。

(继承自 Object)
Reset()

将事件的状态设置为非对齐状态,这会导致线程阻止。

Set()

将事件的状态设置为信号,这允许等待事件继续的一个或多个线程。

ToString()

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

(继承自 Object)
Wait()

阻止当前线程,直到设置当前 ManualResetEventSlim 线程。

Wait(CancellationToken)

阻止当前线程,直到当前 ManualResetEventSlim 接收信号,同时观察一个 CancellationToken

Wait(Int32, CancellationToken)

阻止当前线程,直到设置当前 ManualResetEventSlim 线程,使用 32 位带符号整数测量时间间隔,同时观察一个 CancellationToken

Wait(Int32)

阻止当前线程,直到设置当前 ManualResetEventSlim 线程,使用 32 位有符号整数测量时间间隔。

Wait(TimeSpan, CancellationToken)

阻止当前线程,直到设置当前 ManualResetEventSlim 线程,使用 a TimeSpan 测量时间间隔,同时观察一个 CancellationToken

Wait(TimeSpan)

使用度量TimeSpan时间间隔,阻止当前线程,直到设置当前ManualResetEventSlim线程。

适用于

线程安全性

所有公共和受保护的成员 ManualResetEventSlim 都是线程安全的,并且可能同时从多个线程使用,但 Dispose 除外,这只能用于已完成所有其他操作 ManualResetEventSlim 时使用,而重置只能在没有其他线程访问该事件时使用。

另请参阅