Lire en anglais

Partager via


Lazy<T> Constructeurs

Définition

Initialise une nouvelle instance de la classe Lazy<T>.

Surcharges

Lazy<T>()

Initialise une nouvelle instance de la classe Lazy<T>. Lorsque l’initialisation différée se produit, le constructeur sans paramètre du type cible est utilisé.

Lazy<T>(Boolean)

Initialise une nouvelle instance de la classe Lazy<T>. Lorsque l’initialisation différée se produit, le constructeur sans paramètre du type cible et le mode d’initialisation spécifié sont utilisés.

Lazy<T>(Func<T>)

Initialise une nouvelle instance de la classe Lazy<T>. Lorsque l’initialisation différée se produit, la fonction d’initialisation spécifiée est utilisée.

Lazy<T>(LazyThreadSafetyMode)

Initialise une nouvelle instance de la classe Lazy<T> qui utilise le constructeur sans paramètre de T et le mode de sécurité de thread spécifié.

Lazy<T>(T)

Initialise une nouvelle instance de la classe Lazy<T> qui utilise une valeur spécifiée préinitialisée.

Lazy<T>(Func<T>, Boolean)

Initialise une nouvelle instance de la classe Lazy<T>. Lorsque l’initialisation différée se produit, la fonction d’initialisation et le mode d’initialisation spécifiés sont utilisés.

Lazy<T>(Func<T>, LazyThreadSafetyMode)

Initialise une nouvelle instance de la classe Lazy<T> qui utilise la fonction d’initialisation et le mode de sécurité des threads spécifiés.

Lazy<T>()

Source:
Lazy.cs
Source:
Lazy.cs
Source:
Lazy.cs

Initialise une nouvelle instance de la classe Lazy<T>. Lorsque l’initialisation différée se produit, le constructeur sans paramètre du type cible est utilisé.

C#
public Lazy ();

Exemples

L’exemple suivant illustre l’utilisation de ce constructeur. Il illustre également l’utilisation du constructeur Lazy<T>(Boolean) (spécification de true pour isThreadSafe) et du constructeur Lazy<T>(LazyThreadSafetyMode) (spécification de LazyThreadSafetyMode.ExecutionAndPublication pour mode). Pour basculer vers un autre constructeur, modifiez simplement les constructeurs qui sont commentés.

L’exemple définit une classe LargeObject qui sera initialisée de manière différée par l’un de plusieurs threads. Les deux lignes de code clés de cet exemple sont la création de l’initialiseur et l’initialisation réelle. Au début de la méthode Main, l’exemple crée l’initialiseur différé thread-safe pour LargeObject:

C#
lazyLargeObject = new Lazy<LargeObject>();

// The following lines show how to use other constructors to achieve exactly the
// same result as the previous line:
//lazyLargeObject = new Lazy<LargeObject>(true);
//lazyLargeObject = new Lazy<LargeObject>(LazyThreadSafetyMode.ExecutionAndPublication);

L’exemple crée et démarre trois threads qui bloquent sur un objet ManualResetEvent, afin que l’exemple puisse libérer tous les threads en même temps. La méthode ThreadProc utilisée par les trois threads appelle la propriété Value pour obtenir l’instance LargeObject :

C#
LargeObject large = lazyLargeObject.Value;

La classe Lazy<T> fournit un verrouillage, afin qu’un seul thread soit autorisé à créer l’instance LargeObject. L’exemple montre que les autres threads obtiennent toutes la même instance.

Note

Par souci de simplicité, cet exemple utilise une instance globale de Lazy<T>, et toutes les méthodes sont static (Shared en Visual Basic). Ces conditions ne sont pas requises pour l’utilisation de l’initialisation différée.

C#
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>();

        // The following lines show how to use other constructors to achieve exactly the
        // same result as the previous line:
        //lazyLargeObject = new Lazy<LargeObject>(true);
        //lazyLargeObject = new Lazy<LargeObject>(LazyThreadSafetyMode.ExecutionAndPublication);

        Console.WriteLine(
            "\r\nLargeObject is not created until you access the Value property of the lazy" +
            "\r\ninitializer. Press Enter to create LargeObject.");
        Console.ReadLine();

        // 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(100);
        startingGate.Set();

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

        Console.WriteLine("\r\nPress 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("Initialized by thread {0}; last used by thread {1}.",
                large.InitializedBy, large.Data[0]);
        }
    }
}

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

    public LargeObject()
    {
        initBy = Thread.CurrentThread.ManagedThreadId;
        Console.WriteLine("LargeObject was created on thread id {0}.", initBy);
    }
    public long[] Data = new long[100000000];
}

/* This example produces output similar to the following:

LargeObject is not created until you access the Value property of the lazy
initializer. Press Enter to create LargeObject.

LargeObject was created on thread id 4.
Initialized by thread 4; last used by thread 3.
Initialized by thread 4; last used by thread 4.
Initialized by thread 4; last used by thread 5.

Press Enter to end the program
 */

Remarques

Une instance créée avec ce constructeur peut être utilisée simultanément à partir de plusieurs threads.

Le mode de sécurité de thread d’une instance de Lazy<T> initialisée avec ce constructeur est LazyThreadSafetyMode.ExecutionAndPublication. Le mode de sécurité des threads décrit le comportement lorsque plusieurs threads essaient d’initialiser l’instance Lazy<T>.

Une instance Lazy<T> créée avec ce constructeur ne met pas en cache les exceptions. Pour plus d’informations, consultez la classe Lazy<T> ou l’énumération System.Threading.LazyThreadSafetyMode.

Voir aussi

S’applique à

.NET 9 et autres versions
Produit Versions
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.0, 2.1
UWP 10.0

Lazy<T>(Boolean)

Source:
Lazy.cs
Source:
Lazy.cs
Source:
Lazy.cs

Initialise une nouvelle instance de la classe Lazy<T>. Lorsque l’initialisation différée se produit, le constructeur sans paramètre du type cible et le mode d’initialisation spécifié sont utilisés.

C#
public Lazy (bool isThreadSafe);

Paramètres

isThreadSafe
Boolean

true pour rendre cette instance utilisable simultanément par plusieurs threads ; false pour rendre l’instance utilisable par un seul thread à la fois.

Exemples

L’exemple suivant illustre l’utilisation de ce constructeur pour créer un initialiseur différé qui n’est pas thread-safe, pour les scénarios où tous les accès à l’objet initialisé différé se produisent sur le même thread. Il illustre également l’utilisation du constructeur Lazy<T>(LazyThreadSafetyMode) (en spécifiant LazyThreadSafetyMode.None pour mode. Pour basculer vers un autre constructeur, modifiez simplement le constructeur qui est commenté.

Note

Pour le code qui montre comment utiliser ce constructeur dans des scénarios multithreads (en spécifiant true pour isThreadSafe), consultez l’exemple du constructeur Lazy<T>().

L’exemple définit une classe LargeObject qui sera initialisée de manière différée. Dans la méthode Main, l’exemple crée une instance de Lazy<T>, puis s’interrompt. Lorsque vous appuyez sur la touche Entrée , l’exemple accède à la propriété de l’instance , ce qui entraîne l’initialisation. Le constructeur de la classe LargeObject affiche un message console.

Note

Par souci de simplicité, cet exemple utilise une instance globale de Lazy<T>, et toutes les méthodes sont static (Shared en Visual Basic). Ces conditions ne sont pas requises pour l’utilisation de l’initialisation différée.

C#
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>(false);

        // The following lines show how to use other constructors to achieve exactly the
        // same result as the previous line:
        //lazyLargeObject = new Lazy<LargeObject>(LazyThreadSafetyMode.None);

        Console.WriteLine(
            "\r\nLargeObject is not created until you access the Value property of the lazy" +
            "\r\ninitializer. Press Enter to create LargeObject.");
        Console.ReadLine();

        LargeObject large = lazyLargeObject.Value;

        large.Data[11] = 89;

        Console.WriteLine("\r\nPress Enter to end the program");
        Console.ReadLine();
    }
}

class LargeObject
{
    public LargeObject()
    {
        Console.WriteLine("LargeObject was created on thread id {0}.",
            Thread.CurrentThread.ManagedThreadId);
    }
    public long[] Data = new long[100000000];
}

/* This example produces output similar to the following:

LargeObject is not created until you access the Value property of the lazy
initializer. Press Enter to create LargeObject.

LargeObject was created on thread id 1.

Press Enter to end the program
 */

Remarques

Le mode de sécurité de thread d’une instance de Lazy<T> initialisée avec ce constructeur est LazyThreadSafetyMode.ExecutionAndPublication si isThreadSafe est true; sinon, le mode est LazyThreadSafetyMode.None. Le mode de sécurité des threads décrit le comportement lorsque plusieurs threads essaient d’initialiser l’instance Lazy<T>. Pour spécifier le mode LazyThreadSafetyMode.PublicationOnly, utilisez le constructeur Lazy<T>(Func<T>, LazyThreadSafetyMode) ou Lazy<T>(LazyThreadSafetyMode).

Une instance Lazy<T> créée avec ce constructeur ne met pas en cache les exceptions. Pour plus d’informations, consultez la classe Lazy<T> ou l’énumération System.Threading.LazyThreadSafetyMode.

Voir aussi

S’applique à

.NET 9 et autres versions
Produit Versions
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.0, 2.1
UWP 10.0

Lazy<T>(Func<T>)

Source:
Lazy.cs
Source:
Lazy.cs
Source:
Lazy.cs

Initialise une nouvelle instance de la classe Lazy<T>. Lorsque l’initialisation différée se produit, la fonction d’initialisation spécifiée est utilisée.

C#
public Lazy (Func<T> valueFactory);

Paramètres

valueFactory
Func<T>

Délégué appelé pour produire la valeur initialisée de manière différée lorsqu’il est nécessaire.

Exceptions

valueFactory est null.

Exemples

L’exemple suivant illustre l’utilisation de ce constructeur pour fournir une initialisation différée avec mise en cache d’exception. Il illustre également l’utilisation du constructeur Lazy<T>(Func<T>, Boolean) (spécification de true pour isThreadSafe) et du constructeur Lazy<T>(Func<T>, LazyThreadSafetyMode) (spécification de LazyThreadSafetyMode.ExecutionAndPublication pour mode). Pour basculer vers un autre constructeur, modifiez simplement les constructeurs qui sont commentés.

L’exemple définit une classe LargeObject qui sera initialisée de manière différée par l’un de plusieurs threads. Les trois sections clés du code illustrent la création de l’initialiseur, l’initialisation réelle et le constructeur de la classe LargeObject, qui illustre la mise en cache des exceptions. Au début de la méthode Main, l’exemple crée l’initialiseur différé thread-safe pour LargeObject:

C#
lazyLargeObject = new Lazy<LargeObject>(InitLargeObject);

// The following lines show how to use other constructors to achieve exactly the
// same result as the previous line:
//lazyLargeObject = new Lazy<LargeObject>(InitLargeObject, true);
//lazyLargeObject = new Lazy<LargeObject>(InitLargeObject, LazyThreadSafetyMode.ExecutionAndPublication);

L’exemple crée et démarre trois threads. La méthode ThreadProc utilisée par les trois threads appelle la propriété Value pour obtenir l’instance LargeObject :

C#
try
{
    LargeObject large = lazyLargeObject.Value;

    // 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("Initialized by thread {0}; last used by thread {1}.",
            large.InitializedBy, large.Data[0]);
    }
}
catch (ApplicationException aex)
{
    Console.WriteLine("Exception: {0}", aex.Message);
}

Dans le constructeur de la classe LargeObject, la troisième section clé du code lève une exception la première fois qu’une instance de LargeObject est créée, mais permet ensuite la création d’une instance :

C#
static int instanceCount = 0;
public LargeObject()
{
    if (1 == Interlocked.Increment(ref instanceCount))
    {
        throw new ApplicationException("Throw only ONCE.");
    }

    initBy = Thread.CurrentThread.ManagedThreadId;
    Console.WriteLine("LargeObject was created on thread id {0}.", initBy);
}

Lorsque l’exemple est exécuté, le premier thread qui tente de créer une instance de LargeObject échoue et l’exception est interceptée. Vous pouvez vous attendre à ce que le thread suivant crée une instance, mais que l’objet Lazy<T> a mis en cache l’exception. En raison de cela, les trois threads lèvent l’exception.

Note

Par souci de simplicité, cet exemple utilise une instance globale de Lazy<T>, et toutes les méthodes sont static (Shared en Visual Basic). Ces conditions ne sont pas requises pour l’utilisation de l’initialisation différée.

C#
using System;
using System.Threading;

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

    static LargeObject InitLargeObject()
    {
        return new LargeObject();
    }

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

        // The following lines show how to use other constructors to achieve exactly the
        // same result as the previous line:
        //lazyLargeObject = new Lazy<LargeObject>(InitLargeObject, true);
        //lazyLargeObject = new Lazy<LargeObject>(InitLargeObject, LazyThreadSafetyMode.ExecutionAndPublication);

        Console.WriteLine(
            "\r\nLargeObject is not created until you access the Value property of the lazy" +
            "\r\ninitializer. Press Enter to create LargeObject.");
        Console.ReadLine();

        // Create and start 3 threads, each of which tries to use LargeObject.
        Thread[] threads = { new Thread(ThreadProc), new Thread(ThreadProc), new Thread(ThreadProc) };
        foreach (Thread t in threads)
        {
            t.Start();
        }

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

        Console.WriteLine("\r\nPress Enter to end the program");
        Console.ReadLine();
    }

    static void ThreadProc(object state)
    {
        try
        {
            LargeObject large = lazyLargeObject.Value;

            // 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("Initialized by thread {0}; last used by thread {1}.",
                    large.InitializedBy, large.Data[0]);
            }
        }
        catch (ApplicationException aex)
        {
            Console.WriteLine("Exception: {0}", aex.Message);
        }
    }
}

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

    static int instanceCount = 0;
    public LargeObject()
    {
        if (1 == Interlocked.Increment(ref instanceCount))
        {
            throw new ApplicationException("Throw only ONCE.");
        }

        initBy = Thread.CurrentThread.ManagedThreadId;
        Console.WriteLine("LargeObject was created on thread id {0}.", initBy);
    }
    public long[] Data = new long[100000000];
}

/* This example produces output similar to the following:

LargeObject is not created until you access the Value property of the lazy
initializer. Press Enter to create LargeObject.

Exception: Throw only ONCE.
Exception: Throw only ONCE.
Exception: Throw only ONCE.

Press Enter to end the program
 */

Remarques

Une instance créée avec ce constructeur peut être utilisée simultanément à partir de plusieurs threads.

Le mode de sécurité de thread d’une instance de Lazy<T> initialisée avec ce constructeur est LazyThreadSafetyMode.ExecutionAndPublication. Le mode de sécurité des threads décrit le comportement lorsque plusieurs threads essaient d’initialiser l’instance Lazy<T>.

Les exceptions levées par valueFactory sont mises en cache. Pour plus d’informations, consultez la classe Lazy<T> ou l’énumération System.Threading.LazyThreadSafetyMode.

Voir aussi

S’applique à

.NET 9 et autres versions
Produit Versions
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.0, 2.1
UWP 10.0

Lazy<T>(LazyThreadSafetyMode)

Source:
Lazy.cs
Source:
Lazy.cs
Source:
Lazy.cs

Initialise une nouvelle instance de la classe Lazy<T> qui utilise le constructeur sans paramètre de T et le mode de sécurité de thread spécifié.

C#
public Lazy (System.Threading.LazyThreadSafetyMode mode);

Paramètres

mode
LazyThreadSafetyMode

Une des valeurs d’énumération qui spécifie le mode de sécurité du thread.

Exceptions

mode contient une valeur non valide.

Exemples

L’exemple suivant illustre l’utilisation de ce constructeur pour créer un initialiseur différé qui permet à plusieurs threads de se courser pour créer un objet de manière différée. Plusieurs threads peuvent réussir à créer des instances, mais tous les threads utilisent l’instance créée en premier.

Note

Pour obtenir un exemple qui montre comment utiliser ce constructeur dans des scénarios à thread unique (en spécifiant LazyThreadSafetyMode.None pour mode), consultez le constructeur Lazy<T>(Boolean). Pour obtenir un exemple qui montre comment utiliser ce constructeur pour fournir un verrouillage au lieu de conditions de concurrence dans des scénarios multithreads (en spécifiant LazyThreadSafetyMode.ExecutionAndPublication pour mode), consultez le constructeur Lazy<T>().

L’exemple définit une classe LargeObject qui sera initialisée de manière différée par l’un des plusieurs threads. Les trois sections clés du code illustrent la création de l’initialiseur, l’initialisation réelle et le constructeur et le finaliseur de la classe LargeObject. Au début de la méthode Main, l’exemple crée l’objet Lazy<T> qui effectue une initialisation différée du LargeObject:

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

L’exemple crée et démarre trois threads qui bloquent sur un objet ManualResetEvent, afin que l’exemple puisse libérer tous les threads en même temps. Dans la méthode ThreadProc utilisée par les trois threads, l’appel de la propriété Value crée l’instance LargeObject :

C#
LargeObject large = lazyLargeObject.Value;

Étant donné que le constructeur de l’instance Lazy<T> spécifiée LazyThreadSafetyMode.PublicationOnly, les trois threads sont autorisés à créer des instances LargeObject. L’exemple illustre cela en affichant les messages de console dans le constructeur et dans le finaliseur de la classe LargeObject :

C#
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);
}

Toutefois, l’objet Lazy<T> garantit qu’une seule instance est utilisée par tous les threads. La sortie de l’exemple montre que les trois threads utilisent la même instance et montrent également que les deux autres instances peuvent être récupérées par garbage collection.

Note

Par souci de simplicité, cet exemple utilise une instance globale de Lazy<T>, et toutes les méthodes sont static (Shared en Visual Basic). Ces conditions ne sont pas requises pour l’utilisation de l’initialisation différée.

C#
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
 */

Remarques

Le mode de sécurité de thread d’une instance de Lazy<T> décrit le comportement lorsque plusieurs threads essaient d’initialiser l’instance Lazy<T>.

Une instance Lazy<T> créée avec ce constructeur ne met pas en cache les exceptions. Pour plus d’informations, consultez la classe Lazy<T> ou l’énumération System.Threading.LazyThreadSafetyMode.

Voir aussi

S’applique à

.NET 9 et autres versions
Produit Versions
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.0, 2.1
UWP 10.0

Lazy<T>(T)

Source:
Lazy.cs
Source:
Lazy.cs
Source:
Lazy.cs

Initialise une nouvelle instance de la classe Lazy<T> qui utilise une valeur spécifiée préinitialisée.

C#
public Lazy (T value);

Paramètres

value
T

Valeur préinitialisée à utiliser.

Remarques

Une instance créée avec ce constructeur est utilisable simultanément par plusieurs threads.

S’applique à

.NET 9 et autres versions
Produit Versions
.NET Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Standard 2.1

Lazy<T>(Func<T>, Boolean)

Source:
Lazy.cs
Source:
Lazy.cs
Source:
Lazy.cs

Initialise une nouvelle instance de la classe Lazy<T>. Lorsque l’initialisation différée se produit, la fonction d’initialisation et le mode d’initialisation spécifiés sont utilisés.

C#
public Lazy (Func<T> valueFactory, bool isThreadSafe);

Paramètres

valueFactory
Func<T>

Délégué appelé pour produire la valeur initialisée de manière différée lorsqu’il est nécessaire.

isThreadSafe
Boolean

true pour rendre cette instance utilisable simultanément par plusieurs threads ; false pour rendre cette instance utilisable par un seul thread à la fois.

Exceptions

valueFactory est null.

Exemples

L’exemple suivant illustre l’utilisation de ce constructeur pour fournir une initialisation différée avec mise en cache d’exceptions, dans un scénario avec un thread unique. Il illustre également l’utilisation du constructeur Lazy<T> (en spécifiant LazyThreadSafetyMode.None pour mode). Pour basculer vers ce constructeur, modifiez simplement le constructeur qui est commenté.

Note

Pour le code qui montre comment utiliser ce constructeur dans des scénarios multithreads (en spécifiant true pour isThreadSafe), consultez l’exemple du constructeur Lazy<T>(Func<T>).

L’exemple définit une classe LargeObject qui sera initialisée de manière différée par l’un de plusieurs threads. Les trois sections clés du code illustrent la création de l’initialiseur, l’initialisation réelle et le constructeur de la classe LargeObject, qui illustre la mise en cache des exceptions. Au début de la méthode Main, l’exemple crée l’initialiseur différé thread-safe pour LargeObject:

C#
lazyLargeObject = new Lazy<LargeObject>(InitLargeObject, false);

// The following lines show how to use other constructors to achieve exactly the
// same result as the previous line:
//lazyLargeObject = new Lazy<LargeObject>(InitLargeObject, LazyThreadSafetyMode.None);

Dans l’appel au constructeur, le paramètre isThreadSafe est false, de sorte que le Lazy<T> n’est pas thread-safe. Étant donné qu’il n’est pas thread sécurisé, l’exemple appelle la propriété Value trois fois sur le même thread :

C#
for (int i = 0; i < 3; i++)
{
    try
    {
        LargeObject large = lazyLargeObject.Value;
        large.Data[11] = 89;
    }
    catch (ApplicationException aex)
    {
        Console.WriteLine("Exception: {0}", aex.Message);
    }
}

Dans le constructeur de la classe LargeObject, la troisième section clé du code lève une exception la première fois qu’une instance de LargeObject est créée, mais permet ensuite la création d’une instance :

C#
static bool pleaseThrow = true;
public LargeObject()
{
    if (pleaseThrow)
    {
        pleaseThrow = false;
        throw new ApplicationException("Throw only ONCE.");
    }

    Console.WriteLine("LargeObject was created on thread id {0}.",
        Thread.CurrentThread.ManagedThreadId);
}

Lorsque l’exemple est exécuté, la première tentative de création d’une instance de LargeObject échoue et l’exception est interceptée. Vous pouvez vous attendre à ce que la prochaine tentative réussisse, mais que l’objet Lazy<T> a mis en cache l’exception. En raison de cela, les trois tentatives lèvent l’exception.

Note

Par souci de simplicité, cet exemple utilise une instance globale de Lazy<T>, et toutes les méthodes sont static (Shared en Visual Basic). Ces conditions ne sont pas requises pour l’utilisation de l’initialisation différée.

C#
using System;
using System.Threading;

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

    static LargeObject InitLargeObject()
    {
        return new LargeObject();
    }

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

        // The following lines show how to use other constructors to achieve exactly the
        // same result as the previous line:
        //lazyLargeObject = new Lazy<LargeObject>(InitLargeObject, LazyThreadSafetyMode.None);

        Console.WriteLine(
            "\r\nLargeObject is not created until you access the Value property of the lazy" +
            "\r\ninitializer. Press Enter to create LargeObject (three tries).");
        Console.ReadLine();

        for (int i = 0; i < 3; i++)
        {
            try
            {
                LargeObject large = lazyLargeObject.Value;
                large.Data[11] = 89;
            }
            catch (ApplicationException aex)
            {
                Console.WriteLine("Exception: {0}", aex.Message);
            }
        }

        Console.WriteLine("\r\nPress Enter to end the program");
        Console.ReadLine();
    }
}

class LargeObject
{
    static bool pleaseThrow = true;
    public LargeObject()
    {
        if (pleaseThrow)
        {
            pleaseThrow = false;
            throw new ApplicationException("Throw only ONCE.");
        }

        Console.WriteLine("LargeObject was created on thread id {0}.",
            Thread.CurrentThread.ManagedThreadId);
    }
    public long[] Data = new long[100000000];
}

/* This example produces output similar to the following:

LargeObject is not created until you access the Value property of the lazy
initializer. Press Enter to create LargeObject (three tries).

Exception: Throw only ONCE.
Exception: Throw only ONCE.
Exception: Throw only ONCE.

Press Enter to end the program
 */

Remarques

Le mode de sécurité de thread d’une instance de Lazy<T> initialisée avec ce constructeur est LazyThreadSafetyMode.ExecutionAndPublication si isThreadSafe est true; sinon, le mode est LazyThreadSafetyMode.None. Le mode de sécurité des threads décrit le comportement lorsque plusieurs threads essaient d’initialiser l’instance Lazy<T>.

Pour spécifier le mode LazyThreadSafetyMode.PublicationOnly, utilisez le constructeur Lazy<T>(Func<T>, LazyThreadSafetyMode) ou Lazy<T>(LazyThreadSafetyMode).

Les exceptions levées par valueFactory sont mises en cache. Pour plus d’informations, consultez la classe Lazy<T> ou l’énumération System.Threading.LazyThreadSafetyMode.

Voir aussi

S’applique à

.NET 9 et autres versions
Produit Versions
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.0, 2.1
UWP 10.0

Lazy<T>(Func<T>, LazyThreadSafetyMode)

Source:
Lazy.cs
Source:
Lazy.cs
Source:
Lazy.cs

Initialise une nouvelle instance de la classe Lazy<T> qui utilise la fonction d’initialisation et le mode de sécurité des threads spécifiés.

C#
public Lazy (Func<T> valueFactory, System.Threading.LazyThreadSafetyMode mode);

Paramètres

valueFactory
Func<T>

Délégué appelé pour produire la valeur initialisée de manière différée lorsqu’il est nécessaire.

mode
LazyThreadSafetyMode

Une des valeurs d’énumération qui spécifie le mode de sécurité du thread.

Exceptions

mode contient une valeur non valide.

valueFactory est null.

Exemples

L’exemple suivant illustre l’utilisation de ce constructeur pour créer un initialiseur différé qui permet à plusieurs threads de se courser pour créer un objet de manière différée. Plusieurs threads peuvent réussir à créer des instances, mais tous les threads utilisent l’instance créée en premier. En outre, l’exemple montre que les exceptions ne sont jamais mises en cache lorsque vous spécifiez LazyThreadSafetyMode.PublicationOnly, même si l’initialisation est effectuée par une fonction plutôt que par le constructeur sans paramètre du type créé parzily.

Note

Pour obtenir un exemple qui montre comment utiliser ce constructeur dans des scénarios à thread unique (en spécifiant LazyThreadSafetyMode.None pour mode), consultez le constructeur Lazy<T>(Boolean). Pour obtenir un exemple qui montre comment utiliser ce constructeur pour fournir un verrouillage au lieu de conditions de concurrence dans des scénarios multithreads (en spécifiant LazyThreadSafetyMode.ExecutionAndPublication pour mode), consultez le constructeur Lazy<T>().

L’exemple définit une classe LargeObject qui sera initialisée de manière différée par l’un des plusieurs threads. Les quatre sections clés du code illustrent la création de l’initialiseur, l’initialisation réelle, la fonction d’initialisation et le constructeur et le finaliseur de la classe LargeObject. Au début de la méthode Main, l’exemple crée l’objet Lazy<T> qui effectue une initialisation différée du LargeObject:

C#
lazyLargeObject = new Lazy<LargeObject>(InitLargeObject,
                             LazyThreadSafetyMode.PublicationOnly);

L’initialiseur différé utilise une fonction pour effectuer l’initialisation. Dans ce cas, une fonction est requise, car il n’existe aucun constructeur sans paramètre pour la classe LargeObject.

L’exemple crée et démarre trois threads qui bloquent sur un objet ManualResetEvent, afin que l’exemple puisse libérer tous les threads en même temps. Dans la méthode ThreadProc utilisée par les trois threads, l’appel de la propriété Value crée l’instance LargeObject :

C#
LargeObject large = null;
try
{
    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]);
    }
}
catch (ApplicationException ex)
{
    Console.WriteLine("ApplicationException: {0}", ex.Message);
}

Dans la troisième section clé du code, la fonction d’initialisation différée est appelée pour créer l’instance LargeObject. La fonction lève une exception la première fois qu’elle est appelée :

C#
static int instanceCount = 0;
static LargeObject InitLargeObject()
{
    if (1 == Interlocked.Increment(ref instanceCount))
    {
        throw new ApplicationException(
            String.Format("Lazy initialization function failed on thread {0}.",
            Thread.CurrentThread.ManagedThreadId));
    }
    return new LargeObject(Thread.CurrentThread.ManagedThreadId);
}

Avec tout autre paramètre de LazyThreadSafetyMode, une exception non gérée dans la fonction d’initialisation est mise en cache. Toutefois, LazyThreadSafetyMode.PublicationOnly supprime la mise en cache des exceptions. La sortie de l’exemple montre qu’une tentative d’initialisation de l’objet réussit.

Note

Le message d’exception apparaît généralement après les messages indiquant que d’autres threads ont correctement initialisé l’objet. Cela est dû au délai introduit par la levée et l’interception de l’exception.

Étant donné que le constructeur de l’instance Lazy<T> spécifiée LazyThreadSafetyMode.PublicationOnly, les trois threads sont autorisés à créer des instances LargeObject. L’exemple illustre cela en affichant les messages de console dans le constructeur et dans le finaliseur de la classe LargeObject :

C#
public LargeObject(int initializedBy)
{
    initBy = initializedBy;
    Console.WriteLine("Constructor: Instance initializing on thread {0}", initBy);
}

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

L’objet Lazy<T> garantit qu’une seule instance est utilisée par tous les threads (à l’exception du thread où la fonction d’initialisation lève une exception). La sortie de l’exemple montre ceci.

Note

Par souci de simplicité, cet exemple utilise une instance globale de Lazy<T>, et toutes les méthodes sont static (Shared en Visual Basic). Ces conditions ne sont pas requises pour l’utilisation de l’initialisation différée.

C#
using System;
using System.Threading;

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

    // Factory function for lazy initialization.
    static int instanceCount = 0;
    static LargeObject InitLargeObject()
    {
        if (1 == Interlocked.Increment(ref instanceCount))
        {
            throw new ApplicationException(
                String.Format("Lazy initialization function failed on thread {0}.",
                Thread.CurrentThread.ManagedThreadId));
        }
        return new LargeObject(Thread.CurrentThread.ManagedThreadId);
    }

    static void Main()
    {
        // The lazy initializer is created here. LargeObject is not created until the
        // ThreadProc method executes.
        lazyLargeObject = new Lazy<LargeObject>(InitLargeObject,
                                     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 extra instances.");

        GC.Collect();

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

        Console.WriteLine("\r\nNote that only one instance of LargeObject was used.");
        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 = null;
        try
        {
            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]);
            }
        }
        catch (ApplicationException ex)
        {
            Console.WriteLine("ApplicationException: {0}", ex.Message);
        }
    }
}

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

    public LargeObject(int initializedBy)
    {
        initBy = initializedBy;
        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 5
Constructor: Instance initializing on thread 4
ApplicationException: Lazy initialization function failed on thread 3.
LargeObject was initialized by thread 5; last used by thread 5.
LargeObject was initialized by thread 5; last used by thread 4.

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

Note that only one instance of LargeObject was used.
Press Enter to end the program

Finalizer: Instance was initialized on 5
 */

Remarques

Le mode de sécurité de thread d’une instance de Lazy<T> décrit le comportement lorsque plusieurs threads essaient d’initialiser l’instance Lazy<T>.

Les exceptions levées par valueFactory sont mises en cache, sauf si mode est LazyThreadSafetyMode.PublicationOnly. Pour plus d’informations, consultez la classe Lazy<T> ou l’énumération System.Threading.LazyThreadSafetyMode.

Voir aussi

S’applique à

.NET 9 et autres versions
Produit Versions
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.0, 2.1
UWP 10.0