Condividi tramite


ManualResetEventSlim Classe

Definizione

Rappresenta un evento di sincronizzazione dei thread che, quando viene segnalato, deve essere reimpostato manualmente. La classe è un'alternativa leggera a 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
Ereditarietà
ManualResetEventSlim
Attributi
Implementazioni

Esempio

Nell'esempio seguente viene illustrato come usare un oggetto 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

Commenti

È possibile usare questa classe per ottenere prestazioni migliori rispetto a quando si prevede che i tempi di ManualResetEvent attesa siano molto brevi e quando l'evento non supera un limite di processo. ManualResetEventSlim usa una rotazione per un breve periodo di tempo mentre si attende che l'evento venga segnalato. Quando i tempi di attesa sono brevi, la rotazione può essere molto meno costosa rispetto all'attesa tramite handle di attesa. Se tuttavia l'evento non viene segnalato entro un determinato periodo di tempo, ManualResetEventSlim ricorre a una normale attesa di handle dell'evento.

Nota

In .NET Core e .NET 5+, la durata di attesa di rotazione predefinita è breve: in base all'ordine di 10 secondi di microsecondi, a seconda della piattaforma e del processore. Se si prevede che i tempi di ManualResetEvent attesa siano molto più lunghi di questo, è comunque possibile usare questa classe anziché (forse configurata con meno o nessuna rotazione in attesa). Tuttavia, il vantaggio delle prestazioni probabilmente sarebbe solo marginale.

Costruttori

ManualResetEventSlim()

Inizializza una nuova istanza della classe ManualResetEventSlim con uno stato iniziale di non segnalato.

ManualResetEventSlim(Boolean)

Consente l'inizializzazione di una nuova istanza della classe ManualResetEventSlim con un valore Booleano che indica se lo stato iniziale deve essere impostato su segnalato.

ManualResetEventSlim(Boolean, Int32)

Inizializza una nuova istanza della classe ManualResetEventSlim con un valore booleano che indica se impostare lo stato iniziale su segnalato e un conteggio delle rotazioni specificato.

Proprietà

IsSet

Ottiene un valore che indica se l'evento è impostato.

SpinCount

Ottiene il numero di attese di rotazione che devono verificarsi prima di eseguire il fallback su un'operazione di attesa basata sul kernel.

WaitHandle

Ottiene l'oggetto WaitHandle sottostante per questo oggetto ManualResetEventSlim.

Metodi

Dispose()

Rilascia tutte le risorse usate dall'istanza corrente della classe ManualResetEventSlim.

Dispose(Boolean)

Rilascia le risorse non gestite usate dall'oggetto ManualResetEventSlim e, facoltativamente, le risorse gestite.

Equals(Object)

Determina se l'oggetto specificato è uguale all'oggetto corrente.

(Ereditato da Object)
GetHashCode()

Funge da funzione hash predefinita.

(Ereditato da Object)
GetType()

Ottiene l'oggetto Type dell'istanza corrente.

(Ereditato da Object)
MemberwiseClone()

Crea una copia superficiale dell'oggetto Object corrente.

(Ereditato da Object)
Reset()

Imposta lo stato dell'evento su non segnalato, provocando il blocco dei thread.

Set()

Imposta lo stato dell'evento su segnalato, per consentire a uno o più thread in attesa dell'evento di procedere.

ToString()

Restituisce una stringa che rappresenta l'oggetto corrente.

(Ereditato da Object)
Wait()

Blocca il thread corrente finché l'oggetto ManualResetEventSlim corrente non viene impostato.

Wait(CancellationToken)

Blocca il thread corrente finché l'oggetto ManualResetEventSlim corrente non riceve un segnale, osservando un oggetto CancellationToken.

Wait(Int32)

Blocca il thread corrente finché l'oggetto ManualResetEventSlim corrente non viene impostato, utilizzando un intero con segno a 32 bit per misurare l'intervallo di tempo.

Wait(Int32, CancellationToken)

Blocca il thread corrente finché l'oggetto ManualResetEventSlim corrente non viene impostato, utilizzando un intero con segno a 32 bit per misurare l'intervallo di tempo e al contempo osservando un oggetto CancellationToken.

Wait(TimeSpan)

Blocca il thread corrente finché l'oggetto ManualResetEventSlim corrente non viene impostato, utilizzando un oggetto TimeSpan per misurare l'intervallo di tempo.

Wait(TimeSpan, CancellationToken)

Blocca il thread corrente finché l'oggetto ManualResetEventSlim corrente non viene impostato, utilizzando un oggetto TimeSpan per misurare l'intervallo di tempo e al contempo osservando un oggetto CancellationToken.

Si applica a

Thread safety

Tutti i membri pubblici e protetti di ManualResetEventSlim sono thread-safe e possono essere usati contemporaneamente da più thread, ad eccezione di Dispose, che devono essere usati solo quando tutte le altre operazioni sull'oggetto ManualResetEventSlim sono state completate e Reset, che devono essere usate solo quando nessun altro thread accede all'evento.

Vedi anche