Questo articolo è stato tradotto automaticamente. Per visualizzare l'articolo in inglese, selezionare la casella di controllo Inglese. È possibile anche visualizzare il testo inglese in una finestra popup posizionando il puntatore del mouse sopra il testo.
Traduzione
Inglese

Costruttore Lazy<T>(LazyThreadSafetyMode)

 

Data di pubblicazione: ottobre 2016

Inizializza una nuova istanza della classe Lazy<T> che usa il costruttore predefinito di T e la modalità thread safety specificati.

Spazio dei nomi:   System
Assembly:  mscorlib (in mscorlib.dll)

public Lazy(
	LazyThreadSafetyMode mode
)

Parametri

mode
Type: System.Threading.LazyThreadSafetyMode

Uno dei valori di enumerazione che specifica la modalità thread safety.

Exception Condition
ArgumentOutOfRangeException

mode contiene un valore non valido.

La modalità thread safety di un Lazy<T> istanza viene descritto il comportamento quando più thread tentano di inizializzare il Lazy<T> istanza.

Oggetto Lazy<T> istanza che viene creato con questo costruttore non memorizzato nella cache di eccezioni. Per ulteriori informazioni, vedere la classe Lazy<T> o l'enumerazione System.Threading.LazyThreadSafetyMode.

Nell'esempio seguente viene illustrato l'utilizzo di questo costruttore per creare un inizializzatore lazy che consente a più thread per situazioni di race per creare un oggetto in modo differito. Più thread riesca nella creazione di istanze, ma l'istanza è stata creata prima di utilizzare tutti i thread.

System_CAPS_noteNota

Per un esempio che illustra come utilizzare questo costruttore in scenari a thread singolo (specificando LazyThreadSafetyMode.None per mode), vedere il Lazy<T>(Boolean) costruttore. Per un esempio che illustra come utilizzare questo costruttore per fornire il blocco anziché race condition in scenari con multithreading (specificando LazyThreadSafetyMode.ExecutionAndPublication per mode), vedere il Lazy<T>() costruttore.

Nell'esempio viene definito un LargeObject classe che verrà inizializzata in modo differito da uno dei diversi thread. Le tre sezioni principali del codice vengono illustrate la creazione di inizializzatore di, l'effettiva inizializzazione e il costruttore e il finalizzatore della LargeObject classe. All'inizio del Main (metodo), nell'esempio viene creata la Lazy<T> oggetto che esegue l'inizializzazione differita del LargeObject:

lazyLargeObject = new Lazy<LargeObject>(LazyThreadSafetyMode.PublicationOnly);

L'esempio crea e avvia tre thread che bloccano su un ManualResetEvent dell'oggetto, in modo che l'esempio è possibile rilasciare i thread in una sola volta. Nel ThreadProc metodo utilizzato da tutti i thread, la chiamata di Value proprietà crea la LargeObject istanza:

LargeObject large = lazyLargeObject.Value;

Poiché il costruttore per il Lazy<T> istanza specificata LazyThreadSafetyMode.PublicationOnly, tutti i thread sono autorizzati a creare LargeObject istanze. Nell'esempio viene illustrato questo visualizzando i messaggi della console nel costruttore e nel finalizzatore del LargeObject classe:

public LargeObject() 
{ 
    initBy = Thread.CurrentThread.ManagedThreadId;
    Console.WriteLine("Constructor: Instance initializing on thread {0}", initBy);
}

~LargeObject()
{
    Console.WriteLine("Finalizer: Instance was initialized on {0}", initBy);
}

Tuttavia, il Lazy<T> oggetto garantisce che solo un'istanza viene utilizzata da tutti i thread. L'output dell'esempio mostra che tutti i thread utilizzano la stessa istanza e mostra inoltre che le due istanze possono essere recuperate tramite garbage collection.

System_CAPS_noteNota

Per semplicità, in questo esempio viene utilizzata un'istanza globale di Lazy<T> e tutti i metodi sono static (Shared in Visual Basic). Questi non sono requisiti per l'uso di inizializzazione differita.

using System;
using System.Threading;

class Program
{
    static Lazy<LargeObject> lazyLargeObject = null;

    static void Main()
    {
        // The lazy initializer is created here. LargeObject is not created until the 
        // ThreadProc method executes.
        lazyLargeObject = new Lazy<LargeObject>(LazyThreadSafetyMode.PublicationOnly);


        // Create and start 3 threads, passing the same blocking event to all of them.
        ManualResetEvent startingGate = new ManualResetEvent(false);
        Thread[] threads = { new Thread(ThreadProc), new Thread(ThreadProc), new Thread(ThreadProc) };
        foreach (Thread t in threads)
        {
            t.Start(startingGate);
        }

        // Give all 3 threads time to start and wait, then release them all at once.
        Thread.Sleep(50);
        startingGate.Set();

        // Wait for all 3 threads to finish. (The order doesn't matter.)
        foreach (Thread t in threads)
        {
            t.Join();
        }

        Console.WriteLine(
            "\r\nThreads are complete. Running GC.Collect() to reclaim the extra instances.");

        GC.Collect();

        // Allow time for garbage collection, which happens asynchronously.
        Thread.Sleep(100);

        Console.WriteLine( 
            "\r\nNote that all three threads used the instance that was not collected.");
        Console.WriteLine("Press Enter to end the program");
        Console.ReadLine();
    }


    static void ThreadProc(object state)
    {
        // Wait for the signal.
        ManualResetEvent waitForStart = (ManualResetEvent) state;
        waitForStart.WaitOne();

        LargeObject large = lazyLargeObject.Value;

        // The following line introduces an artificial delay, to exaggerate the race 
        // condition.
        Thread.Sleep(5); 

        // IMPORTANT: Lazy initialization is thread-safe, but it doesn't protect the  
        //            object after creation. You must lock the object before accessing it,
        //            unless the type is thread safe. (LargeObject is not thread safe.)
        lock(large)
        {
            large.Data[0] = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("LargeObject was initialized by thread {0}; last used by thread {1}.", 
                large.InitializedBy, large.Data[0]);
        }
    }
}

class LargeObject
{
    int initBy = -1;
    public int InitializedBy { get { return initBy; } }

    public LargeObject() 
    { 
        initBy = Thread.CurrentThread.ManagedThreadId;
        Console.WriteLine("Constructor: Instance initializing on thread {0}", initBy);
    }

    ~LargeObject()
    {
        Console.WriteLine("Finalizer: Instance was initialized on {0}", initBy);
    }

    public long[] Data = new long[100000000];
}

/* This example produces output similar to the following:

Constructor: Instance initializing on thread 4
Constructor: Instance initializing on thread 3
Constructor: Instance initializing on thread 5
LargeObject was initialized by thread 4; last used by thread 4.
LargeObject was initialized by thread 4; last used by thread 5.
LargeObject was initialized by thread 4; last used by thread 3.

Threads are complete. Running GC.Collect() to reclaim the extra instances.
Finalizer: Instance was initialized on 3
Finalizer: Instance was initialized on 5

Note that all three threads used the instance that was not collected.
Press Enter to end the program

Instance finalizing; initialized on 4
 */

Universal Windows Platform
Disponibile da 8
.NET Framework
Disponibile da 4.0
Libreria di classi portabile
Supportato in: piattaforme .NET portabili
Silverlight
Disponibile da 4.0
Windows Phone Silverlight
Disponibile da 8.0
Windows Phone
Disponibile da 8.1
Torna all'inizio
Mostra: