Per i programmi di concorrenza che ho scritto in C #, i miei blocchi / sincronizzazione tendono a seguire questo schema:
try
{
Monitor.Enter(locker);
// critical region
}
finally
{
Monitor.Exit(locker);
}
Questo è uno schema classico che ho scoperto in uno dei libri C # di Paul Deitel anni fa e da allora lo sto seguendo. Questo ha funzionato molto bene per molte applicazioni che ho richiesto. Tuttavia, recentemente ho avuto una discussione con un altro sviluppatore sulla concorrenza e mi hanno chiesto ... perché lo stai facendo in quel modo quando potresti usare "serrature con scope".
A questo punto ammetterò che non avevo idea di cosa fossero. Ho iniziato a scavare per capire se questo potesse essere utile per scrivere le mie applicazioni. Nella mia ricerca ho scoperto questo pattern RAII (l'acquisizione delle risorse è in fase di inizializzazione), che alla mia comprensione consente di bloccare gli ambiti. Immagino che questo pattern sia usato principalmente in C ++ ma ci sono alcune pseudo-implementazioni in C # come segue (tratto da L'acquisizione delle risorse è inizializzazione in C # ):
using System;
namespace RAII
{
public class DisposableDelegate : IDisposable
{
private Action dispose;
public DisposableDelegate(Action dispose)
{
if (dispose == null)
{
throw new ArgumentNullException("dispose");
}
this.dispose = dispose;
}
public void Dispose()
{
if (this.dispose != null)
{
Action d = this.dispose;
this.dispose = null;
d();
}
}
}
class Program
{
static void Main(string[] args)
{
Console.Out.WriteLine("Some resource allocated here.");
using (new DisposableDelegate(() => Console.Out.WriteLine("Resource deallocated here.")))
{
Console.Out.WriteLine("Resource used here.");
throw new InvalidOperationException("Test for resource leaks.");
}
}
}
}
Sto solo cercando di capire come questo modello produce la sincronizzazione in C # ... La sincronizzazione è inerente a qualcosa che ha a che fare con l'allocazione delle risorse?
Inoltre, non è un modo di abusare della lingua per costringere un utente a usare un costruttore w / using
per far funzionare tutto questo? Cosa succede se qualcosa viene cancellato e viene generata un'eccezione in un costruttore? Non vedo dove sia molto meglio del buon vecchio Enter
/ Exit
pattern.