ManualResetEventSlim Classe
Definizione
Importante
Alcune informazioni sono relative alla release non definitiva del prodotto, che potrebbe subire modifiche significative prima della release definitiva. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
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.