Mutex 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.
Primitiva di sincronizzazione che può essere usata anche per la sincronizzazione interprocesso.
public ref class Mutex sealed : System::Threading::WaitHandle
public sealed class Mutex : System.Threading.WaitHandle
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class Mutex : System.Threading.WaitHandle
type Mutex = class
inherit WaitHandle
[<System.Runtime.InteropServices.ComVisible(true)>]
type Mutex = class
inherit WaitHandle
Public NotInheritable Class Mutex
Inherits WaitHandle
- Ereditarietà
- Ereditarietà
- Attributi
Esempio
In questo esempio viene illustrato come viene usato un oggetto locale Mutex per sincronizzare l'accesso a una risorsa protetta. Poiché ogni thread chiamante viene bloccato finché non acquisisce la proprietà del mutex, deve chiamare il ReleaseMutex metodo per rilasciare la proprietà del mutex.
using System;
using System.Threading;
class Example
{
// Create a new Mutex. The creating thread does not own the mutex.
private static Mutex mut = new Mutex();
private const int numIterations = 1;
private const int numThreads = 3;
static void Main()
{
// Create the threads that will use the protected resource.
for(int i = 0; i < numThreads; i++)
{
Thread newThread = new Thread(new ThreadStart(ThreadProc));
newThread.Name = String.Format("Thread{0}", i + 1);
newThread.Start();
}
// The main thread exits, but the application continues to
// run until all foreground threads have exited.
}
private static void ThreadProc()
{
for(int i = 0; i < numIterations; i++)
{
UseResource();
}
}
// This method represents a resource that must be synchronized
// so that only one thread at a time can enter.
private static void UseResource()
{
// Wait until it is safe to enter.
Console.WriteLine("{0} is requesting the mutex",
Thread.CurrentThread.Name);
mut.WaitOne();
Console.WriteLine("{0} has entered the protected area",
Thread.CurrentThread.Name);
// Place code to access non-reentrant resources here.
// Simulate some work.
Thread.Sleep(500);
Console.WriteLine("{0} is leaving the protected area",
Thread.CurrentThread.Name);
// Release the Mutex.
mut.ReleaseMutex();
Console.WriteLine("{0} has released the mutex",
Thread.CurrentThread.Name);
}
}
// The example displays output like the following:
// Thread1 is requesting the mutex
// Thread2 is requesting the mutex
// Thread1 has entered the protected area
// Thread3 is requesting the mutex
// Thread1 is leaving the protected area
// Thread1 has released the mutex
// Thread3 has entered the protected area
// Thread3 is leaving the protected area
// Thread3 has released the mutex
// Thread2 has entered the protected area
// Thread2 is leaving the protected area
// Thread2 has released the mutex
Imports System.Threading
Module Example
' Create a new Mutex. The creating thread does not own the mutex.
Private mut As New Mutex()
Private Const numIterations As Integer = 1
Private Const numThreads As Integer = 3
Public Sub Main()
' Create the threads that will use the protected resource.
For i As Integer = 0 To numThreads - 1
Dim newThread As New Thread(AddressOf ThreadProc)
newThread.Name = String.Format("Thread{0}", i + 1)
newThread.Start()
Next
' The main thread exits, but the application continues to
' run until all foreground threads have exited.
End Sub
Private Sub ThreadProc()
For i As Integer = 0 To numIterations - 1
UseResource()
Next
End Sub
' This method represents a resource that must be synchronized
' so that only one thread at a time can enter.
Private Sub UseResource()
' Wait until it is safe to enter.
Console.WriteLine("{0} is requesting the mutex",
Thread.CurrentThread.Name)
mut.WaitOne()
Console.WriteLine("{0} has entered the protected area",
Thread.CurrentThread.Name)
' Place code to access non-reentrant resources here.
' Simulate some work.
Thread.Sleep(500)
Console.WriteLine("{0} is leaving the protected area",
Thread.CurrentThread.Name)
' Release the Mutex.
mut.ReleaseMutex()
Console.WriteLine("{0} has released the mutex",
Thread.CurrentThread.Name)
End Sub
End Module
' The example displays output like the following:
' Thread1 is requesting the mutex
' Thread2 is requesting the mutex
' Thread1 has entered the protected area
' Thread3 is requesting the mutex
' Thread1 is leaving the protected area
' Thread1 has released the mutex
' Thread3 has entered the protected area
' Thread3 is leaving the protected area
' Thread3 has released the mutex
' Thread2 has entered the protected area
' Thread2 is leaving the protected area
' Thread2 has released the mutex
Nell'esempio seguente ogni thread chiama il metodo per acquisire il WaitOne(Int32) mutex. Se l'intervallo di timeout trascorso, il metodo restituisce false
e il thread non acquisisce il mutex né ottiene l'accesso alla risorsa che il mutex protegge. Il ReleaseMutex metodo viene chiamato solo dal thread che acquisisce il mutex.
using System;
using System.Threading;
class Example
{
// Create a new Mutex. The creating thread does not own the mutex.
private static Mutex mut = new Mutex();
private const int numIterations = 1;
private const int numThreads = 3;
static void Main()
{
Example ex = new Example();
ex.StartThreads();
}
private void StartThreads()
{
// Create the threads that will use the protected resource.
for(int i = 0; i < numThreads; i++)
{
Thread newThread = new Thread(new ThreadStart(ThreadProc));
newThread.Name = String.Format("Thread{0}", i + 1);
newThread.Start();
}
// The main thread returns to Main and exits, but the application continues to
// run until all foreground threads have exited.
}
private static void ThreadProc()
{
for(int i = 0; i < numIterations; i++)
{
UseResource();
}
}
// This method represents a resource that must be synchronized
// so that only one thread at a time can enter.
private static void UseResource()
{
// Wait until it is safe to enter, and do not enter if the request times out.
Console.WriteLine("{0} is requesting the mutex", Thread.CurrentThread.Name);
if (mut.WaitOne(1000)) {
Console.WriteLine("{0} has entered the protected area",
Thread.CurrentThread.Name);
// Place code to access non-reentrant resources here.
// Simulate some work.
Thread.Sleep(5000);
Console.WriteLine("{0} is leaving the protected area",
Thread.CurrentThread.Name);
// Release the Mutex.
mut.ReleaseMutex();
Console.WriteLine("{0} has released the mutex",
Thread.CurrentThread.Name);
}
else {
Console.WriteLine("{0} will not acquire the mutex",
Thread.CurrentThread.Name);
}
}
~Example()
{
mut.Dispose();
}
}
// The example displays output like the following:
// Thread1 is requesting the mutex
// Thread1 has entered the protected area
// Thread2 is requesting the mutex
// Thread3 is requesting the mutex
// Thread2 will not acquire the mutex
// Thread3 will not acquire the mutex
// Thread1 is leaving the protected area
// Thread1 has released the mutex
Imports System.Threading
Class Example
' Create a new Mutex. The creating thread does not own the mutex.
Private mut As New Mutex()
Private Const numIterations As Integer = 1
Private Const numThreads As Integer = 3
Public Shared Sub Main()
Dim ex As New Example()
ex.StartThreads()
End Sub
Private Sub StartThreads()
' Create the threads that will use the protected resource.
For i As Integer = 0 To numThreads - 1
Dim newThread As New Thread(AddressOf ThreadProc)
newThread.Name = String.Format("Thread{0}", i + 1)
newThread.Start()
Next
' The main thread returns to Main and exits, but the application continues to
' run until all foreground threads have exited.
End Sub
Private Sub ThreadProc()
For i As Integer = 0 To numIterations - 1
UseResource()
Next
End Sub
' This method represents a resource that must be synchronized
' so that only one thread at a time can enter.
Private Sub UseResource()
' Wait until it is safe to enter.
Console.WriteLine("{0} is requesting the mutex",
Thread.CurrentThread.Name)
If mut.WaitOne(1000) Then
Console.WriteLine("{0} has entered the protected area",
Thread.CurrentThread.Name)
' Place code to access non-reentrant resources here.
' Simulate some work.
Thread.Sleep(5000)
Console.WriteLine("{0} is leaving the protected area",
Thread.CurrentThread.Name)
' Release the Mutex.
mut.ReleaseMutex()
Console.WriteLine("{0} has released the mutex",
Thread.CurrentThread.Name)
Else
Console.WriteLine("{0} will not acquire the mutex",
Thread.CurrentThread.Name)
End If
End Sub
Protected Overrides Sub Finalize()
mut.Dispose()
End Sub
End Class
' The example displays output like the following:
' Thread1 is requesting the mutex
' Thread1 has entered the protected area
' Thread2 is requesting the mutex
' Thread3 is requesting the mutex
' Thread2 will not acquire the mutex
' Thread3 will not acquire the mutex
' Thread1 is leaving the protected area
' Thread1 has released the mutex
Commenti
Quando due o più thread devono accedere contemporaneamente a una risorsa condivisa, il sistema necessita di un meccanismo di sincronizzazione per garantire che un solo thread alla volta usi la risorsa. Mutex è una primitiva di sincronizzazione che concede l'accesso esclusivo alla risorsa condivisa a un solo thread. Se un thread acquisisce un mutex, il secondo thread che vuole acquisire tale mutex viene sospeso fino a quando il primo thread rilascia il mutex.
Importante
Il tipo implementa l'interfaccia IDisposable. Dopo aver utilizzato il tipo, è necessario eliminarlo direttamente o indirettamente. Per eliminare direttamente il tipo, chiamare il metodo Dispose in un blocco try
/catch
. Per eliminarlo indirettamente, utilizzare un costrutto di linguaggio come ad esempio using
in C# o Using
in Visual Basic. Per altre informazioni, vedere la sezione "Uso di un oggetto che implementa IDisposable" nell'argomento relativo all'interfaccia IDisposable.
È possibile usare il WaitHandle.WaitOne metodo per richiedere la proprietà di un mutex. Il thread chiamante blocca fino a quando non si verifica una delle operazioni seguenti:
Il mutex viene segnalato per indicare che non è di proprietà. In questo caso, il metodo restituisce
true
e il WaitOne thread chiamante presuppone la proprietà del mutex e accede alla risorsa protetta dal mutex. Al termine dell'accesso alla risorsa, il thread deve chiamare il ReleaseMutex metodo per rilasciare la proprietà del mutex. Il primo esempio nella sezione Esempi illustra questo modello.Intervallo di timeout specificato nella chiamata a un WaitOne metodo con un
millisecondsTimeout
parametro otimeout
trascorso. In questo caso, il metodo restituiscefalse
e il WaitOne thread chiamante non tenta ulteriormente di acquisire la proprietà del mutex. In questo caso, è necessario strutturare il codice in modo che l'accesso alla risorsa protetta dal mutex venga negato al thread chiamante. Poiché il thread non ha mai acquisito la proprietà del mutex, non deve chiamare il ReleaseMutex metodo. Il secondo esempio nella sezione Esempi illustra questo modello.
La Mutex classe applica l'identità del thread, quindi un mutex può essere rilasciato solo dal thread che lo ha acquisito. Al contrario, la classe non applica l'identità Semaphore del thread. È anche possibile passare un mutex tra limiti di dominio dell'applicazione.
Il thread proprietario di un mutex può richiedere lo stesso mutex nelle chiamate ripetute a WaitOne senza bloccare l'esecuzione. Tuttavia, il thread deve chiamare il ReleaseMutex metodo lo stesso numero di volte per rilasciare la proprietà del mutex.
Poiché la classe eredita da WaitHandle, è anche possibile chiamare i metodi statici WaitHandle.WaitAll e WaitHandle.WaitAny per sincronizzare l'accesso Mutex a una risorsa protetta.
Se un thread termina durante la proprietà di un mutex, il mutex viene detto di essere abbandonato. Lo stato del mutex è impostato su segnalato e il thread in attesa successivo ottiene la proprietà. A partire dalla versione 2.0 di .NET Framework, viene AbandonedMutexException generata nel thread successivo che acquisisce il mutex abbandonato. Prima della versione 2.0 di .NET Framework, non è stata generata alcuna eccezione.
Attenzione
Un mutex abbandonato spesso indica un errore grave nel codice. Quando un thread viene chiuso senza rilasciare il mutex, le strutture di dati protette dal mutex potrebbero non essere in uno stato coerente. Il thread successivo per richiedere la proprietà del mutex può gestire questa eccezione e procedere, se è possibile verificare l'integrità delle strutture di dati.
Nel caso di un mutex di sistema, un mutex abbandonato potrebbe indicare che un'applicazione è stata terminata in modo anomalo (ad esempio, usando Gestione attività Windows).
I mutex sono di due tipi: mutex locali, che non sono denominati e mutex di sistema denominati. Un mutex locale esiste solo all'interno del processo. Può essere usato da qualsiasi thread nel processo con un riferimento all'oggetto Mutex che rappresenta il mutex. Ogni oggetto senza nome Mutex rappresenta un mutex locale separato.
I mutex di sistema denominati sono visibili in tutto il sistema operativo e possono essere usati per sincronizzare le attività dei processi. È possibile creare un Mutex oggetto che rappresenta un mutex di sistema denominato usando un costruttore che accetta un nome. L'oggetto sistema operativo può essere creato contemporaneamente oppure può esistere prima della creazione dell'oggetto Mutex . È possibile creare più oggetti Mutex che rappresentano lo stesso mutex di sistema denominato ed è possibile usare il metodo OpenExisting per aprire un mutex di sistema denominato esistente.
Nota
In un server che esegue Servizi terminal, un mutex di sistema denominato può avere due livelli di visibilità. Se il nome inizia con il prefisso "Global\", il mutex è visibile in tutte le sessioni del server terminale. Se il nome inizia con il prefisso "Local\", il mutex è visibile solo nella sessione del server terminale in cui è stato creato. In tal caso, un mutex separato con lo stesso nome può esistere in ognuna delle altre sessioni del server terminale nel server. Se non si specifica un prefisso quando si crea un mutex denominato, accetta il prefisso "Local\". All'interno di una sessione del server terminale, due mutex i cui nomi differiscono solo per i relativi prefissi sono mutex separati e entrambi sono visibili a tutti i processi nella sessione del server terminale. Ovvero, i nomi di prefisso "Global" e "Local\\" descrivono l'ambito del nome mutex rispetto alle sessioni del server terminale, non relative ai processi.
La barra rovesciata (\) è un carattere riservato in un nome di mutex. Non usare una barra rovesciata (\) in un nome del mutex, se non come specificato nella nota sull'uso dei mutex nelle sessioni di Terminal Server. In caso contrario, potrebbe essere generata una DirectoryNotFoundException, anche se il nome del mutex rappresenta un file esistente.
Costruttori
Mutex() |
Inizializza una nuova istanza della classe Mutex con le proprietà predefinite. |
Mutex(Boolean) |
Inizializza una nuova istanza della classe Mutex con un valore booleano che indica se il thread chiamante deve avere la proprietà iniziale del mutex. |
Mutex(Boolean, String) |
Inizializza una nuova istanza della classe Mutex con un valore booleano che indica se il thread chiamante deve avere la proprietà iniziale del mutex e con una stringa che rappresenta il nome del mutex. |
Mutex(Boolean, String, Boolean) |
Inizializza una nuova istanza della classe Mutex con un valore booleano che indica se il thread chiamante deve avere la proprietà iniziale del mutex, con una stringa che rappresenta il nome del mutex e con un valore booleano che, quando il metodo viene restituito, indichi se al thread chiamante era stata concessa la proprietà iniziale del mutex. |
Mutex(Boolean, String, Boolean, MutexSecurity) |
Inizializza una nuova istanza della classe Mutex con un valore booleano che indica se il thread chiamante deve avere la proprietà iniziale del mutex, con una stringa che rappresenta il nome del mutex, con una variabile Boolean che, quando il metodo viene restituito, indichi se al thread chiamante era stata concessa la proprietà iniziale del mutex e con la sicurezza del controllo di accesso da applicare al mutex denominato. |
Campi
WaitTimeout |
Indica che si è verificato il timeout di un'operazione WaitAny(WaitHandle[], Int32, Boolean) prima della segnalazione di uno degli handle di attesa. Questo campo è costante. (Ereditato da WaitHandle) |
Proprietà
Handle |
Obsoleta.
Obsoleta.
Ottiene o imposta l'handle nativo del sistema operativo. (Ereditato da WaitHandle) |
SafeWaitHandle |
Ottiene o imposta l'handle nativo del sistema operativo. (Ereditato da WaitHandle) |
Metodi
Close() |
Rilascia tutte le risorse contenute nell'oggetto WaitHandle corrente. (Ereditato da WaitHandle) |
CreateObjRef(Type) |
Consente di creare un oggetto che contiene tutte le informazioni rilevanti necessarie per la generazione del proxy utilizzato per effettuare la comunicazione con un oggetto remoto. (Ereditato da MarshalByRefObject) |
Dispose() |
Rilascia tutte le risorse usate dall'istanza corrente della classe WaitHandle. (Ereditato da WaitHandle) |
Dispose(Boolean) |
Quando ne viene eseguito l'override in una classe derivata, libera le risorse non gestite usate da WaitHandle ed eventualmente di liberare le risorse gestite. (Ereditato da WaitHandle) |
Equals(Object) |
Determina se l'oggetto specificato è uguale all'oggetto corrente. (Ereditato da Object) |
GetAccessControl() |
Ottiene un oggetto MutexSecurity che rappresenta la sicurezza del controllo di accesso per il mutex denominato. |
GetHashCode() |
Funge da funzione hash predefinita. (Ereditato da Object) |
GetLifetimeService() |
Obsoleta.
Consente di recuperare l'oggetto servizio di durata corrente per controllare i criteri di durata per l'istanza. (Ereditato da MarshalByRefObject) |
GetType() |
Ottiene l'oggetto Type dell'istanza corrente. (Ereditato da Object) |
InitializeLifetimeService() |
Obsoleta.
Ottiene un oggetto servizio di durata per controllare i criteri di durata per questa istanza. (Ereditato da MarshalByRefObject) |
MemberwiseClone() |
Crea una copia superficiale dell'oggetto Object corrente. (Ereditato da Object) |
MemberwiseClone(Boolean) |
Crea una copia dei riferimenti dell'oggetto MarshalByRefObject corrente. (Ereditato da MarshalByRefObject) |
OpenExisting(String) |
Apre il mutex denominato specificato, se esistente. |
OpenExisting(String, MutexRights) |
Apre il mutex denominato specificato, se esistente, con l'accesso di sicurezza desiderato. |
ReleaseMutex() |
Rilascia l'oggetto Mutex una volta. |
SetAccessControl(MutexSecurity) |
Imposta la sicurezza del controllo di accesso per un mutex di sistema denominato. |
ToString() |
Restituisce una stringa che rappresenta l'oggetto corrente. (Ereditato da Object) |
TryOpenExisting(String, Mutex) |
Apre il mutex denominato specificato, se esistente, e restituisce un valore che indica se l'operazione è stata completata. |
TryOpenExisting(String, MutexRights, Mutex) |
Apre il mutex denominato specificato, se esistente, con l'accesso di sicurezza desiderato, e restituisce un valore che indica se l'operazione è stata completata. |
WaitOne() |
Blocca il thread corrente finché l'oggetto WaitHandle corrente non riceve un segnale. (Ereditato da WaitHandle) |
WaitOne(Int32) |
Blocca il thread corrente finché l'oggetto WaitHandle corrente non riceve un segnale, usando un intero con segno a 32 bit per specificare l'intervallo di tempo. (Ereditato da WaitHandle) |
WaitOne(Int32, Boolean) |
Blocca il thread corrente finché l'oggetto WaitHandle corrente non riceve un segnale, usando un intero con segno a 32 bit per specificare l'intervallo di tempo e indicando se uscire dal dominio di sincronizzazione prima dell'attesa. (Ereditato da WaitHandle) |
WaitOne(TimeSpan) |
Blocca il thread corrente finché l'istanza corrente non riceve un segnale, usando un valore TimeSpan per specificare l'intervallo di tempo. (Ereditato da WaitHandle) |
WaitOne(TimeSpan, Boolean) |
Blocca il thread corrente finché l'istanza corrente non riceve un segnale, usando un oggetto TimeSpan per specificare l'intervallo di tempo e indicando se uscire dal dominio di sincronizzazione prima dell'attesa. (Ereditato da WaitHandle) |
Implementazioni dell'interfaccia esplicita
IDisposable.Dispose() |
Questa API supporta l'infrastruttura del prodotto e non è previsto che venga usata direttamente dal codice. Rilascia tutte le risorse usate da WaitHandle. (Ereditato da WaitHandle) |
Metodi di estensione
GetAccessControl(Mutex) |
Restituisce i descrittori di sicurezza per l'oggetto |
SetAccessControl(Mutex, MutexSecurity) |
Imposta i descrittori di sicurezza per il mutex specificato. |
GetSafeWaitHandle(WaitHandle) |
Ottiene l'handle sicuro per un handle di attesa nativo del sistema operativo. |
SetSafeWaitHandle(WaitHandle, SafeWaitHandle) |
Imposta un handle sicuro per un handle di attesa nativo del sistema operativo. |
Si applica a
Thread safety
Questo tipo è thread-safe.