Lazy<T> Oluşturucular

Tanım

Lazy<T> sınıfının yeni bir örneğini başlatır.

Aşırı Yüklemeler

Lazy<T>()

Lazy<T> sınıfının yeni bir örneğini başlatır. Gecikmeli başlatma gerçekleştiğinde, hedef türün parametresiz oluşturucu kullanılır.

Lazy<T>(Boolean)

Lazy<T> sınıfının yeni bir örneğini başlatır. Yavaş başlatma gerçekleştiğinde, hedef türün parametresiz oluşturucu ve belirtilen başlatma modu kullanılır.

Lazy<T>(Func<T>)

Lazy<T> sınıfının yeni bir örneğini başlatır. Gecikmeli başlatma gerçekleştiğinde, belirtilen başlatma işlevi kullanılır.

Lazy<T>(LazyThreadSafetyMode)

sınıfının parametresiz oluşturucuyu T ve belirtilen iş parçacığı güvenliği modunu kullanan yeni bir örneğini Lazy<T> başlatır.

Lazy<T>(T)

Önceden başlatılmamış belirtilen değeri kullanan sınıfının yeni bir örneğini Lazy<T> başlatır.

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

Lazy<T> sınıfının yeni bir örneğini başlatır. Gecikmeli başlatma gerçekleştiğinde, belirtilen başlatma işlevi ve başlatma modu kullanılır.

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

Belirtilen başlatma işlevini ve iş parçacığı güvenliği modunu kullanan sınıfının yeni bir örneğini Lazy<T> başlatır.

Lazy<T>()

Kaynak:
Lazy.cs
Kaynak:
Lazy.cs
Kaynak:
Lazy.cs

Lazy<T> sınıfının yeni bir örneğini başlatır. Gecikmeli başlatma gerçekleştiğinde, hedef türün parametresiz oluşturucu kullanılır.

public:
 Lazy();
public Lazy ();
Public Sub New ()

Örnekler

Aşağıdaki örnekte bu oluşturucunun kullanımı gösterilmektedir. Ayrıca oluşturucunun Lazy<T>(Boolean) (için isThreadSafebelirterek) ve oluşturucunun Lazy<T>(LazyThreadSafetyMode) (için modebelirterek trueLazyThreadSafetyMode.ExecutionAndPublication) kullanımını da gösterir. Farklı bir oluşturucuya geçmek için açıklama satırı yapılan oluşturucuları değiştirmeniz gerekir.

Örnek, birkaç iş parçacığından biri tarafından yavaş başlatılacak bir LargeObject sınıf tanımlar. Bu örnekteki iki önemli kod satırı başlatıcının oluşturulması ve gerçek başlatmadır. Yöntemin Main başında, örnek için LargeObjectiş parçacığı güvenli yavaş başlatıcıyı oluşturur:

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);
let lazyLargeObject = Lazy<LargeObject>()

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

' The following lines show how to use other constructors to achieve exactly the
' same result as the previous line: 
'lazyLargeObject = New Lazy(Of LargeObject)(True)
'lazyLargeObject = New Lazy(Of LargeObject)(LazyThreadSafetyMode.ExecutionAndPublication)

Örnek, bir ManualResetEvent nesne üzerinde blok oluşturan ve başlatan üç iş parçacığı oluşturur ve başlatır, böylece örnek iş parçacıklarının tümünü aynı anda serbest bırakabilir. ThreadProc Üç iş parçacığı tarafından kullanılan yöntem, örneği almak LargeObject için özelliğini çağırırValue:

LargeObject large = lazyLargeObject.Value;
let large = lazyLargeObject.Value
Dim large As LargeObject = lazyLargeObject.Value

Lazy<T> sınıfı, yalnızca bir iş parçacığının örneği oluşturmasına LargeObject izin vermesi için kilitleme sağlar. Örnek, diğer iş parçacıklarının tümünün aynı örneği elde ettiğini gösterir.

Not

Kolaylık olması için, bu örnekte genel bir örneği Lazy<T>kullanılır ve tüm yöntemler (Shared Visual Basic'te) şeklindedir static . Bunlar yavaş başlatmanın kullanılması için bir gereksinim değildir.

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
 */
open System
open System.Threading

type LargeObject() =
    let initBy = Thread.CurrentThread.ManagedThreadId
    do
        printfn $"LargeObject was created on thread id {initBy}."

    member val Data = Array.zeroCreate<int64> 100000000 with get
    member _.InitializedBy = initBy

// The lazy initializer is created here. LargeObject is not created until the
// ThreadProc method executes.
let lazyLargeObject = Lazy<LargeObject>()

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

let threadProc (state: obj) =
    // Wait for the signal.
    let waitForStart = state :?> ManualResetEvent
    waitForStart.WaitOne() |> ignore

    let 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 (fun () -> 
        large.Data[0] <- Thread.CurrentThread.ManagedThreadId
        printfn $"Initialized by thread {large.InitializedBy} last used by thread {large.Data[0]}." )

printfn """
LargeObject is not created until you access the Value property of the lazy
initializer. Press Enter to create LargeObject."""
stdin.ReadLine() |> ignore

// Create and start 3 threads, passing the same blocking event to all of them.
let startingGate = new ManualResetEvent false
let threads = [| Thread(ParameterizedThreadStart threadProc); Thread(ParameterizedThreadStart threadProc); Thread(ParameterizedThreadStart threadProc) |]
for t in threads do
    t.Start startingGate

// Give all 3 threads time to start and wait, then release them all at once.
Thread.Sleep 100
startingGate.Set() |> ignore

// Wait for all 3 threads to finish. (The order doesn't matter.)
for t in threads do
    t.Join()

printfn "\nPress Enter to end the program"
stdin.ReadLine() |> ignore

// 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
Imports System.Threading

Class Program
    Private Shared lazyLargeObject As Lazy(Of LargeObject) = Nothing

    Shared Sub Main()
        ' The lazy initializer is created here. LargeObject is not created until the 
        ' ThreadProc method executes.
        lazyLargeObject = New Lazy(Of LargeObject)()

        ' The following lines show how to use other constructors to achieve exactly the
        ' same result as the previous line: 
        'lazyLargeObject = New Lazy(Of LargeObject)(True)
        'lazyLargeObject = New Lazy(Of LargeObject)(LazyThreadSafetyMode.ExecutionAndPublication)


        Console.WriteLine( _
            vbCrLf & "LargeObject is not created until you access the Value property of the lazy" _
            & vbCrLf & "initializer. Press Enter to create LargeObject.")
        Console.ReadLine()

        ' Create and start 3 threads, passing the same blocking event to all of them.
        Dim startingGate As New ManualResetEvent(False)
        Dim threads() As Thread = { New Thread(AddressOf ThreadProc), 
            New Thread(AddressOf ThreadProc), New Thread(AddressOf ThreadProc) }
        For Each t As Thread In threads
            t.Start(startingGate)
        Next t

        ' 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.)
        For Each t As Thread In threads
            t.Join()
        Next t

        Console.WriteLine(vbCrLf & "Press Enter to end the program")
        Console.ReadLine()
    End Sub


    Private Shared Sub ThreadProc(ByVal state As Object)
        ' Wait for the signal.
        Dim waitForStart As ManualResetEvent = CType(state, ManualResetEvent)
        waitForStart.WaitOne()

        Dim large As LargeObject = 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.)
        SyncLock large
            large.Data(0) = Thread.CurrentThread.ManagedThreadId
            Console.WriteLine("Initialized by thread {0}; last used by thread {1}.", _
                large.InitializedBy, large.Data(0))
        End SyncLock
    End Sub
End Class

Class LargeObject
    Private initBy As Integer = 0
    Public ReadOnly Property InitializedBy() As Integer
        Get
            Return initBy
        End Get
    End Property

    Public Sub New()
        initBy = Thread.CurrentThread.ManagedThreadId
        Console.WriteLine("LargeObject was created on thread id {0}.", initBy)
    End Sub
    Public Data(100000000) As Long
End Class

' 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 3.
'Initialized by thread 3; last used by thread 5.
'Initialized by thread 3; last used by thread 4.
'Initialized by thread 3; last used by thread 3.
'
'Press Enter to end the program

Açıklamalar

Bu oluşturucu ile oluşturulan bir örnek birden çok iş parçacığından eşzamanlı olarak kullanılabilir.

Bu oluşturucu ile başlatılan bir Lazy<T> örneğin iş parçacığı güvenlik modu şeklindedir LazyThreadSafetyMode.ExecutionAndPublication. İş parçacığı güvenlik modu, birden çok iş parçacığı örneği başlatmaya çalıştığındaki Lazy<T> davranışı açıklar.

Lazy<T> Bu oluşturucu ile oluşturulan bir örnek özel durumları önbelleğe almaz. Daha fazla bilgi için sınıfına Lazy<T> veya numaralandırmaya System.Threading.LazyThreadSafetyMode bakın.

Ayrıca bkz.

Şunlara uygulanır

Lazy<T>(Boolean)

Kaynak:
Lazy.cs
Kaynak:
Lazy.cs
Kaynak:
Lazy.cs

Lazy<T> sınıfının yeni bir örneğini başlatır. Yavaş başlatma gerçekleştiğinde, hedef türün parametresiz oluşturucu ve belirtilen başlatma modu kullanılır.

public:
 Lazy(bool isThreadSafe);
public Lazy (bool isThreadSafe);
new Lazy<'T> : bool -> Lazy<'T>
Public Sub New (isThreadSafe As Boolean)

Parametreler

isThreadSafe
Boolean

true bu örneği birden çok iş parçacığı tarafından eşzamanlı olarak kullanılabilir hale getirmek için; false örneği aynı anda yalnızca bir iş parçacığı tarafından kullanılabilir hale getirmek için.

Örnekler

Aşağıdaki örnek, aynı iş parçacığında yavaş başlatılan nesneye tüm erişimin gerçekleştiği senaryolar için iş parçacığı güvenli olmayan gecikmeli bir başlatıcı oluşturmak için bu oluşturucunun kullanımını gösterir. Ayrıca oluşturucunun Lazy<T>(LazyThreadSafetyMode) kullanımını da gösterir (için modebelirtirLazyThreadSafetyMode.None). Farklı bir oluşturucuya geçmek için açıklama satırı yapılan oluşturucuyu değiştirmeniz gerekir.

Not

Bu oluşturucunun çok iş parçacıklı senaryolarda (için belirterek true ) nasıl kullanılacağını gösteren kod için isThreadSafeoluşturucu örneğine Lazy<T>() bakın.

Örnek, yavaş başlatılacak bir LargeObject sınıf tanımlar. yönteminde Main , örnek bir Lazy<T> örnek oluşturur ve ardından duraklatılır. Enter tuşuna bastığınızda örnek, örneğin özelliğine ValueLazy<T> erişir ve bu da başlatmanın gerçekleşmesine neden olur. sınıfının oluşturucusunun LargeObject bir konsol iletisi görüntüler.

Not

Kolaylık olması için, bu örnekte genel bir örneği Lazy<T>kullanılır ve tüm yöntemler (Shared Visual Basic'te) şeklindedir static . Bunlar yavaş başlatmanın kullanılması için bir gereksinim değildir.

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
 */
open System
open System.Threading

type LargeObject () =
    do
        printfn $"LargeObject was created on thread id {Thread.CurrentThread.ManagedThreadId}."

    member val Data = Array.zeroCreate<int64> 100000000 with get

// The lazy initializer is created here. LargeObject is not created until the
// ThreadProc method executes.
let lazyLargeObject = Lazy<LargeObject> false
// The following lines show how to use other constructors to achieve exactly the
// same result as the previous line:
//     let lazyLargeObject = Lazy<LargeObject>(LazyThreadSafetyMode.None)

printfn """
LargeObject is not created until you access the Value property of the lazy
initializer. Press Enter to create LargeObject."""
stdin.ReadLine() |> ignore

let large = lazyLargeObject.Value

large.Data[11] <- 89

printfn "\nPress Enter to end the program"
stdin.ReadLine() |> ignore


// 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
Imports System.Threading

Friend Class Program
    Private Shared lazyLargeObject As Lazy(Of LargeObject) = Nothing

    Shared Sub Main()
        ' The lazy initializer is created here. LargeObject is not created until the 
        ' ThreadProc method executes.
        lazyLargeObject = New Lazy(Of 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( _
            vbCrLf & "LargeObject is not created until you access the Value property of the lazy" _
            & vbCrLf & "initializer. Press Enter to create LargeObject.")
        Console.ReadLine()

        Dim large As LargeObject = lazyLargeObject.Value

        large.Data(11) = 89

        Console.WriteLine(vbCrLf & "Press Enter to end the program")
        Console.ReadLine()
    End Sub
End Class

Friend Class LargeObject
    Public Sub New()
        Console.WriteLine("LargeObject was created on thread id {0}.", _
            Thread.CurrentThread.ManagedThreadId)
    End Sub
    Public Data(100000000) As Long
End Class

' 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

Açıklamalar

Bu oluşturucu LazyThreadSafetyMode.ExecutionAndPublicationisThreadSafe ile başlatılan bir Lazy<T> örneğin iş parçacığı güvenlik modu ise true; değilse modu şeklindedirLazyThreadSafetyMode.None. İş parçacığı güvenlik modu, birden çok iş parçacığı örneği başlatmaya çalıştığındaki Lazy<T> davranışı açıklar. Modu belirtmek LazyThreadSafetyMode.PublicationOnly için veya Lazy<T>(LazyThreadSafetyMode) oluşturucuyu Lazy<T>(Func<T>, LazyThreadSafetyMode) kullanın.

Lazy<T> Bu oluşturucu ile oluşturulan bir örnek özel durumları önbelleğe almaz. Daha fazla bilgi için sınıfına Lazy<T> veya numaralandırmaya System.Threading.LazyThreadSafetyMode bakın.

Ayrıca bkz.

Şunlara uygulanır

Lazy<T>(Func<T>)

Kaynak:
Lazy.cs
Kaynak:
Lazy.cs
Kaynak:
Lazy.cs

Lazy<T> sınıfının yeni bir örneğini başlatır. Gecikmeli başlatma gerçekleştiğinde, belirtilen başlatma işlevi kullanılır.

public:
 Lazy(Func<T> ^ valueFactory);
public Lazy (Func<T> valueFactory);
new Lazy<'T> : Func<'T> -> Lazy<'T>
Public Sub New (valueFactory As Func(Of T))

Parametreler

valueFactory
Func<T>

Gerektiğinde lazily initialized değerini üretmek için çağrılan temsilci.

Özel durumlar

valueFactory, null değeridir.

Örnekler

Aşağıdaki örnek, özel durum önbelleğe alma ile yavaş başlatma sağlamak için bu oluşturucunun kullanımını gösterir. Ayrıca oluşturucunun Lazy<T>(Func<T>, Boolean) (için isThreadSafebelirterek) ve oluşturucunun Lazy<T>(Func<T>, LazyThreadSafetyMode) (için modebelirterek trueLazyThreadSafetyMode.ExecutionAndPublication) kullanımını da gösterir. Farklı bir oluşturucuya geçmek için açıklama satırı yapılan oluşturucuları değiştirmeniz gerekir.

Örnek, birkaç iş parçacığından biri tarafından yavaş başlatılacak bir LargeObject sınıf tanımlar. Kodun üç önemli bölümü başlatıcının oluşturulmasını, gerçek başlatmayı ve özel durum önbelleğe almayı gösteren sınıfın LargeObject oluşturucusunu gösterir. Yöntemin Main başında, örnek için LargeObjectiş parçacığı güvenli yavaş başlatıcıyı oluşturur:

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);
let lazyLargeObject = Lazy<LargeObject> initLargeObject

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

' The following lines show how to use other constructors to achieve exactly the
' same result as the previous line: 
'lazyLargeObject = New Lazy(Of LargeObject)(AddressOf InitLargeObject, True)
'lazyLargeObject = New Lazy(Of LargeObject)(AddressOf InitLargeObject, LazyThreadSafetyMode.ExecutionAndPublication)

Örnek üç iş parçacığı oluşturur ve başlatır. ThreadProc Üç iş parçacığı tarafından kullanılan yöntem, örneği almak LargeObject için özelliğini çağırırValue:

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);
}
try
    let 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 (fun () -> 
        large.Data[0] <- Thread.CurrentThread.ManagedThreadId
        printfn $"Initialized by thread {large.InitializedBy} last used by thread {large.Data[0]}.")
with :? ApplicationException as aex ->
    printfn $"Exception: {aex.Message}"
Try
    Dim large As LargeObject = 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.)
    SyncLock large
        large.Data(0) = Thread.CurrentThread.ManagedThreadId
        Console.WriteLine("Initialized by thread {0}; last used by thread {1}.", _
            large.InitializedBy, large.Data(0))
    End SyncLock
Catch aex As ApplicationException
    Console.WriteLine("Exception: {0}", aex.Message)
End Try

sınıfının oluşturucusunda LargeObject , kodun üçüncü anahtar bölümü bir örneği ilk kez oluşturulduğunda bir LargeObject özel durum oluşturur, ancak bundan sonra örnek oluşturmanın gerçekleşmesine izin verir:

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);
}
type LargeObject() =
    static let mutable instanceCount = 0
    let initBy = Thread.CurrentThread.ManagedThreadId
    do
        if 1 = Interlocked.Increment &instanceCount then
            raise (ApplicationException "Throw only ONCE.")
        printfn $"LargeObject was created on thread id {initBy}."
Private Shared instanceCount As Integer = 0
Public Sub New()
    If 1 = Interlocked.Increment(instanceCount) Then
        Throw New ApplicationException("Throw only ONCE.")
    End If

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

Örnek çalıştırıldığında, örneğini LargeObject oluşturmaya çalışan ilk iş parçacığı başarısız olur ve özel durum yakalanırsa. Sonraki iş parçacığının başarıyla bir örnek oluşturmasını Lazy<T> bekleyebilirsiniz, ancak nesne özel durumu önbelleğe aldı. Bu nedenle, üç iş parçacığı da özel durum oluşturur.

Not

Kolaylık olması için, bu örnekte genel bir örneği Lazy<T>kullanılır ve tüm yöntemler (Shared Visual Basic'te) şeklindedir static . Bunlar yavaş başlatmanın kullanılması için bir gereksinim değildir.

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
 */
open System
open System.Threading

type LargeObject() =
    static let mutable instanceCount = 0
    let initBy = Thread.CurrentThread.ManagedThreadId
    do
        if 1 = Interlocked.Increment &instanceCount then
            raise (ApplicationException "Throw only ONCE.")
        printfn $"LargeObject was created on thread id {initBy}."
    member _.InitializedBy = initBy
    member val Data = Array.zeroCreate<int64> 100000000

let initLargeObject () =
    LargeObject()

// The lazy initializer is created here. LargeObject is not created until the
// ThreadProc method executes.
let lazyLargeObject = Lazy<LargeObject> initLargeObject

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

let threadProc _ =
    try
        let 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 (fun () -> 
            large.Data[0] <- Thread.CurrentThread.ManagedThreadId
            printfn $"Initialized by thread {large.InitializedBy} last used by thread {large.Data[0]}.")
    with :? ApplicationException as aex ->
        printfn $"Exception: {aex.Message}"

printfn """
LargeObject is not created until you access the Value property of the lazy
initializer. Press Enter to create LargeObject."""
stdin.ReadLine () |> ignore

// Create and start 3 threads, each of which tries to use LargeObject.
let threads = 
    [| Thread(ParameterizedThreadStart threadProc); Thread(ParameterizedThreadStart threadProc); Thread(ParameterizedThreadStart threadProc) |]
for t in threads do
    t.Start()

// Wait for all 3 threads to finish. (The order doesn't matter.)
for t in threads do
    t.Join()

printfn "\nPress Enter to end the program"
stdin.ReadLine() |> ignore

// 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
Imports System.Threading

Friend Class Program
    Private Shared lazyLargeObject As Lazy(Of LargeObject) = Nothing

    Private Shared Function InitLargeObject() As LargeObject
        Return New LargeObject()
    End Function


    Shared Sub Main()
        ' The lazy initializer is created here. LargeObject is not created until the 
        ' ThreadProc method executes.
        lazyLargeObject = New Lazy(Of LargeObject)(AddressOf InitLargeObject)

        ' The following lines show how to use other constructors to achieve exactly the
        ' same result as the previous line: 
        'lazyLargeObject = New Lazy(Of LargeObject)(AddressOf InitLargeObject, True)
        'lazyLargeObject = New Lazy(Of LargeObject)(AddressOf InitLargeObject, LazyThreadSafetyMode.ExecutionAndPublication)


        Console.WriteLine(vbCrLf _
            & "LargeObject is not created until you access the Value property of the lazy" _
            & vbCrLf & "initializer. Press Enter to create LargeObject.")
        Console.ReadLine()

        ' Create and start 3 threads, each of which tries to use LargeObject.
        Dim threads() As Thread = { New Thread(AddressOf ThreadProc), _
            New Thread(AddressOf ThreadProc), New Thread(AddressOf ThreadProc) }
        For Each t As Thread In threads
            t.Start()
        Next t

        ' Wait for all 3 threads to finish. (The order doesn't matter.)
        For Each t As Thread In threads
            t.Join()
        Next t

        Console.WriteLine(vbCrLf & "Press Enter to end the program")
        Console.ReadLine()
    End Sub


    Private Shared Sub ThreadProc(ByVal state As Object)
        Try
            Dim large As LargeObject = 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.)
            SyncLock large
                large.Data(0) = Thread.CurrentThread.ManagedThreadId
                Console.WriteLine("Initialized by thread {0}; last used by thread {1}.", _
                    large.InitializedBy, large.Data(0))
            End SyncLock
        Catch aex As ApplicationException
            Console.WriteLine("Exception: {0}", aex.Message)
        End Try
    End Sub
End Class

Friend Class LargeObject
    Private initBy As Integer = 0
    Public ReadOnly Property InitializedBy() As Integer
        Get
            Return initBy
        End Get
    End Property

    Private Shared instanceCount As Integer = 0
    Public Sub New()
        If 1 = Interlocked.Increment(instanceCount) Then
            Throw New ApplicationException("Throw only ONCE.")
        End If

        initBy = Thread.CurrentThread.ManagedThreadId
        Console.WriteLine("LargeObject was created on thread id {0}.", initBy)
    End Sub
    Public Data(99999999) As Long
End Class

' 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
'

Açıklamalar

Bu oluşturucu ile oluşturulan bir örnek birden çok iş parçacığından eşzamanlı olarak kullanılabilir.

Bu oluşturucu ile başlatılan bir Lazy<T> örneğin iş parçacığı güvenlik modu şeklindedir LazyThreadSafetyMode.ExecutionAndPublication. İş parçacığı güvenlik modu, birden çok iş parçacığı örneği başlatmaya çalıştığındaki Lazy<T> davranışı açıklar.

tarafından valueFactory oluşan özel durumlar önbelleğe alınır. Daha fazla bilgi için sınıfına Lazy<T> veya numaralandırmaya System.Threading.LazyThreadSafetyMode bakın.

Ayrıca bkz.

Şunlara uygulanır

Lazy<T>(LazyThreadSafetyMode)

Kaynak:
Lazy.cs
Kaynak:
Lazy.cs
Kaynak:
Lazy.cs

sınıfının parametresiz oluşturucuyu T ve belirtilen iş parçacığı güvenliği modunu kullanan yeni bir örneğini Lazy<T> başlatır.

public:
 Lazy(System::Threading::LazyThreadSafetyMode mode);
public Lazy (System.Threading.LazyThreadSafetyMode mode);
new Lazy<'T> : System.Threading.LazyThreadSafetyMode -> Lazy<'T>
Public Sub New (mode As LazyThreadSafetyMode)

Parametreler

mode
LazyThreadSafetyMode

İş parçacığı güvenlik modunu belirten numaralandırma değerlerinden biri.

Özel durumlar

mode geçersiz bir değer içeriyor.

Örnekler

Aşağıdaki örnek, birden çok iş parçacığının nesne oluşturmak için yavaş bir başlatıcı oluşturmasına olanak tanıyan bir yavaş başlatıcı oluşturmak için bu oluşturucunun kullanımını gösterir. Birden çok iş parçacığı örnek oluşturmada başarılı olabilir, ancak tüm iş parçacıkları önce oluşturulan örneği kullanır.

Not

Bu oluşturucunun tek iş parçacıklı senaryolarda (için belirterek LazyThreadSafetyMode.None ) nasıl kullanılacağını gösteren bir örnek için modeoluşturucuya Lazy<T>(Boolean) bakın. Çok iş parçacıklı senaryolarda (için belirterek LazyThreadSafetyMode.ExecutionAndPublication ) yarış koşulları yerine kilitleme sağlamak için bu oluşturucunun nasıl kullanılacağını gösteren bir örnek için mode, oluşturucuya Lazy<T>() bakın.

Örnek, birkaç iş parçacığından herhangi biri tarafından yavaş başlatılacak bir LargeObject sınıf tanımlar. Kodun üç önemli bölümü başlatıcının oluşturulmasını, gerçek başlatmayı ve sınıfın oluşturucu ve sonlandırıcısını LargeObject gösterir. Yöntemin Main başında, örnek yavaş başlatma LargeObjectişlemi gerçekleştiren nesnesini oluştururLazy<T>:

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

Örnek, bir ManualResetEvent nesne üzerinde blok oluşturan ve başlatan üç iş parçacığı oluşturur ve başlatır, böylece örnek iş parçacıklarının tümünü aynı anda serbest bırakabilir. ThreadProc Üç iş parçacığı tarafından kullanılan yönteminde özelliğini çağırmak Value örneği oluştururLargeObject:

LargeObject large = lazyLargeObject.Value;
let large = lazyLargeObject.Value
Dim large As LargeObject = lazyLargeObject.Value

Örneğin oluşturucusunun belirttiğindenLazyThreadSafetyMode.PublicationOnly, üç iş parçacığının Lazy<T> da örnek oluşturmasına LargeObject izin verilir. Örnek, oluşturucuda ve sınıfın sonlandırıcısında LargeObject konsol iletilerini görüntüleyerek bunu gösterir:

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);
}
type LargeObject() =
    let initBy = Thread.CurrentThread.ManagedThreadId
    do
        printfn $"Constructor: Instance initializing on thread {initBy}"

    override _.Finalize() =
        printfn $"Finalizer: Instance was initialized on {initBy}"
Public Sub New()
    initBy = Thread.CurrentThread.ManagedThreadId
    Console.WriteLine("Constructor: Instance initializing on thread {0}", initBy)
End Sub

Protected Overrides Sub Finalize()
    Console.WriteLine("Finalizer: Instance was initialized on {0}", initBy)
End Sub

Ancak nesnesi, Lazy<T> tüm iş parçacıkları tarafından yalnızca bir örneğin kullanılmasını sağlar. Örnekten elde edilen çıktı, üç iş parçacığının da aynı örneği kullandığını ve diğer iki örneğin çöp toplama tarafından geri kazanılabildiğini gösterir.

Not

Kolaylık olması için, bu örnekte genel bir örneği Lazy<T>kullanılır ve tüm yöntemler (Shared Visual Basic'te) şeklindedir static . Bunlar yavaş başlatmanın kullanılması için bir gereksinim değildir.

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
 */
open System
open System.Threading

type LargeObject() =
    let initBy = Thread.CurrentThread.ManagedThreadId
    do
        printfn $"Constructor: Instance initializing on thread {initBy}"

    override _.Finalize() =
        printfn $"Finalizer: Instance was initialized on {initBy}"

    member _.InitializedBy = initBy
    member val Data = Array.zeroCreate<int64> 100000000

// The lazy initializer is created here. LargeObject is not created until the
// ThreadProc method executes.
let lazyLargeObject = Lazy<LargeObject> LazyThreadSafetyMode.PublicationOnly

let threadProc (state: obj) =
    // Wait for the signal.
    let waitForStart = state :?> ManualResetEvent
    waitForStart.WaitOne() |> ignore

    let 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 (fun () -> 
        large.Data[0] <- Thread.CurrentThread.ManagedThreadId
        printfn $"LargeObject was initialized by thread {large.InitializedBy} last used by thread {large.Data[0]}.")

// Create and start 3 threads, passing the same blocking event to all of them.
let startingGate = new ManualResetEvent false
let threads = 
    [| Thread(ParameterizedThreadStart threadProc); Thread(ParameterizedThreadStart threadProc); Thread(ParameterizedThreadStart threadProc) |]
for t in threads do
    t.Start startingGate

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

// Wait for all 3 threads to finish. (The order doesn't matter.)
for t in threads do
    t.Join()

printfn "\nThreads are complete. Running GC.Collect() to reclaim the extra instances."

GC.Collect()

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

printfn "\nNote that all three threads used the instance that was not collected."
printfn "Press Enter to end the program"
stdin.ReadLine() |> ignore


// 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
Imports System.Threading

Friend Class Program
    Private Shared lazyLargeObject As Lazy(Of LargeObject) = Nothing

    Shared Sub Main()
        ' The lazy initializer is created here. LargeObject is not created until the 
        ' ThreadProc method executes.
        lazyLargeObject = New Lazy(Of LargeObject)(LazyThreadSafetyMode.PublicationOnly)


        ' Create and start 3 threads, passing the same blocking event to all of them.
        Dim startingGate As New ManualResetEvent(False)
        Dim threads() As Thread = { _
            New Thread(AddressOf ThreadProc), _
            New Thread(AddressOf ThreadProc), _
            New Thread(AddressOf ThreadProc) _
        }
        For Each t As Thread In threads
            t.Start(startingGate)
        Next t

        ' 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.)
        For Each t As Thread In threads
            t.Join()
        Next t

        Console.WriteLine(vbCrLf & _
            "Threads 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(vbCrLf & _
            "Note that all three threads used the instance that was not collected.")
        Console.WriteLine("Press Enter to end the program")
        Console.ReadLine()

    End Sub


    Private Shared Sub ThreadProc(ByVal state As Object)
        ' Wait for the signal.
        Dim waitForStart As ManualResetEvent = CType(state, ManualResetEvent)
        waitForStart.WaitOne()

        Dim large As LargeObject = 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.)
        SyncLock 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))
        End SyncLock
    End Sub
End Class

Friend Class LargeObject
    Private initBy As Integer = -1
    Public ReadOnly Property InitializedBy() As Integer
        Get
            Return initBy
        End Get
    End Property

    Public Sub New()
        initBy = Thread.CurrentThread.ManagedThreadId
        Console.WriteLine("Constructor: Instance initializing on thread {0}", initBy)
    End Sub

    Protected Overrides Sub Finalize()
        Console.WriteLine("Finalizer: Instance was initialized on {0}", initBy)
    End Sub

    Public Data(100000000) As Long
End Class

' This example produces output similar to the following:
'
'Constructor: Instance initializing on thread 3
'Constructor: Instance initializing on thread 5
'Constructor: Instance initializing on thread 4
'LargeObject was initialized by thread 3; last used by thread 4.
'LargeObject was initialized by thread 3; last used by thread 3.
'LargeObject was initialized by thread 3; last used by thread 5.
'
'Threads are complete. Running GC.Collect() to reclaim the extra instances.
'Finalizer: Instance was initialized on 5
'Finalizer: Instance was initialized on 4
'
'Note that all three threads used the instance that was not collected.
'Press Enter to end the program
'
'Finalizer: Instance was initialized on 3
'

Açıklamalar

Bir Lazy<T> örneğin iş parçacığı güvenlik modu, birden çok iş parçacığı örneği başlatmaya çalıştığında oluşan Lazy<T> davranışı açıklar.

Lazy<T> Bu oluşturucu ile oluşturulan bir örnek özel durumları önbelleğe almaz. Daha fazla bilgi için sınıfına Lazy<T> veya numaralandırmaya System.Threading.LazyThreadSafetyMode bakın.

Ayrıca bkz.

Şunlara uygulanır

Lazy<T>(T)

Kaynak:
Lazy.cs
Kaynak:
Lazy.cs
Kaynak:
Lazy.cs

Önceden başlatılmamış belirtilen değeri kullanan sınıfının yeni bir örneğini Lazy<T> başlatır.

public:
 Lazy(T value);
public Lazy (T value);
new Lazy<'T> : 'T -> Lazy<'T>
Public Sub New (value As T)

Parametreler

value
T

Kullanılacak önceden başlatılmamış değer.

Açıklamalar

Bu oluşturucuyla oluşturulan bir örnek, aynı anda birden çok iş parçacığı tarafından kullanılabilir.

Şunlara uygulanır

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

Kaynak:
Lazy.cs
Kaynak:
Lazy.cs
Kaynak:
Lazy.cs

Lazy<T> sınıfının yeni bir örneğini başlatır. Gecikmeli başlatma gerçekleştiğinde, belirtilen başlatma işlevi ve başlatma modu kullanılır.

public:
 Lazy(Func<T> ^ valueFactory, bool isThreadSafe);
public Lazy (Func<T> valueFactory, bool isThreadSafe);
new Lazy<'T> : Func<'T> * bool -> Lazy<'T>
Public Sub New (valueFactory As Func(Of T), isThreadSafe As Boolean)

Parametreler

valueFactory
Func<T>

Gerektiğinde lazily initialized değerini üretmek için çağrılan temsilci.

isThreadSafe
Boolean

true bu örneği birden çok iş parçacığı tarafından eşzamanlı olarak kullanılabilir hale getirmek için; false bu örneği aynı anda yalnızca bir iş parçacığı tarafından kullanılabilir hale getirmek için.

Özel durumlar

valueFactory, null değeridir.

Örnekler

Aşağıdaki örnekte, tek bir iş parçacığı ile bir senaryoda özel durum önbelleğe alma ile yavaş başlatma sağlamak için bu oluşturucunun kullanımı gösterilmektedir. Ayrıca oluşturucunun Lazy<T> kullanımını da gösterir (için modebelirtirLazyThreadSafetyMode.None). Bu oluşturucuya geçmek için açıklama satırı yapılan oluşturucuyu değiştirmeniz gerekir.

Not

Bu oluşturucunun çok iş parçacıklı senaryolarda (için belirterek true ) nasıl kullanılacağını gösteren kod için isThreadSafeoluşturucu örneğine Lazy<T>(Func<T>) bakın.

Örnek, birkaç iş parçacığından biri tarafından yavaş başlatılacak bir LargeObject sınıf tanımlar. Kodun üç önemli bölümü başlatıcının oluşturulmasını, gerçek başlatmayı ve özel durum önbelleğe almayı gösteren sınıfın LargeObject oluşturucusunu gösterir. Yöntemin Main başında, örnek için LargeObjectiş parçacığı güvenli yavaş başlatıcıyı oluşturur:

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);
let lazyLargeObject = Lazy<LargeObject>(initLargeObject, false)

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

' The following lines show how to use other constructors to achieve exactly the
' same result as the previous line: 
'lazyLargeObject = New Lazy(Of LargeObject)(AddressOf InitLargeObject, LazyThreadSafetyMode.None)

Oluşturucuya yapılan çağrıda parametresi olurfalse, isThreadSafe bu nedenle Lazy<T> iş parçacığı güvenli değildir. İş parçacığı güvenli olmadığından, örnek aynı iş parçacığında Value özelliğini üç kez çağırır:

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);
    }
}
for _ = 0 to 2 do
    try
        let large = lazyLargeObject.Value
        large.Data[11] <- 89
    with :? ApplicationException as aex ->
        printfn $"Exception: {aex.Message}"
For i As Integer = 0 To 2
    Try
        Dim large As LargeObject = lazyLargeObject.Value
        large.Data(11) = 89
    Catch aex As ApplicationException
        Console.WriteLine("Exception: {0}", aex.Message)
    End Try
Next i

sınıfının oluşturucusunda LargeObject , kodun üçüncü anahtar bölümü bir örneği ilk kez oluşturulduğunda bir LargeObject özel durum oluşturur, ancak bundan sonra örnek oluşturmanın gerçekleşmesine izin verir:

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);
}
type LargeObject() =
    static let mutable pleaseThrow = true
    do
        if pleaseThrow then
            pleaseThrow <- false
            raise (ApplicationException "Throw only ONCE.")
        printfn $"LargeObject was created on thread id {Thread.CurrentThread.ManagedThreadId}."
Private Shared pleaseThrow As Boolean = True
Public Sub New()
    If pleaseThrow Then
        pleaseThrow = False
        Throw New ApplicationException("Throw only ONCE.")
    End If

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

Örnek çalıştırıldığında, ilk örneği LargeObject oluşturma girişimi başarısız olur ve özel durum yakalanılır. Sonraki denemenin başarılı olmasını bekleyebilirsiniz, ancak Lazy<T> nesne özel durumu önbelleğe aldı. Bu nedenle, üç girişim de özel durum oluşturur.

Not

Kolaylık olması için, bu örnekte genel bir örneği Lazy<T>kullanılır ve tüm yöntemler (Shared Visual Basic'te) şeklindedir static . Bunlar yavaş başlatmanın kullanılması için bir gereksinim değildir.

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
 */
open System
open System.Threading

type LargeObject() =
    static let mutable pleaseThrow = true
    do
        if pleaseThrow then
            pleaseThrow <- false
            raise (ApplicationException "Throw only ONCE.")
        printfn $"LargeObject was created on thread id {Thread.CurrentThread.ManagedThreadId}."
    member val Data = Array.zeroCreate<int64> 100000000

let initLargeObject () =
    LargeObject()

// The lazy initializer is created here. LargeObject is not created until the
// ThreadProc method executes.
let lazyLargeObject = Lazy<LargeObject>(initLargeObject, false)

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

printfn """
LargeObject is not created until you access the Value property of the lazy
initializer. Press Enter to create LargeObject (three tries)."""
stdin.ReadLine() |> ignore

for _ = 0 to 2 do
    try
        let large = lazyLargeObject.Value
        large.Data[11] <- 89
    with :? ApplicationException as aex ->
        printfn $"Exception: {aex.Message}"

printfn "\nPress Enter to end the program"
stdin.ReadLine() |> ignore

// 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
Imports System.Threading

Friend Class Program
    Private Shared lazyLargeObject As Lazy(Of LargeObject) = Nothing

    Private Shared Function InitLargeObject() As LargeObject
        Return New LargeObject()
    End Function


    Shared Sub Main()
        ' The lazy initializer is created here. LargeObject is not created until the 
        ' ThreadProc method executes.
        lazyLargeObject = New Lazy(Of LargeObject)(AddressOf InitLargeObject, False)

        ' The following lines show how to use other constructors to achieve exactly the
        ' same result as the previous line: 
        'lazyLargeObject = New Lazy(Of LargeObject)(AddressOf InitLargeObject, LazyThreadSafetyMode.None)


        Console.WriteLine(vbCrLf _
            & "LargeObject is not created until you access the Value property of the lazy" _
            & vbCrLf & "initializer. Press Enter to create LargeObject (three tries).")
        Console.ReadLine()

        For i As Integer = 0 To 2
            Try
                Dim large As LargeObject = lazyLargeObject.Value
                large.Data(11) = 89
            Catch aex As ApplicationException
                Console.WriteLine("Exception: {0}", aex.Message)
            End Try
        Next i

        Console.WriteLine(vbCrLf & "Press Enter to end the program")
        Console.ReadLine()
    End Sub
End Class

Friend Class LargeObject
    Private Shared pleaseThrow As Boolean = True
    Public Sub New()
        If pleaseThrow Then
            pleaseThrow = False
            Throw New ApplicationException("Throw only ONCE.")
        End If

        Console.WriteLine("LargeObject was created on thread id {0}.", _
            Thread.CurrentThread.ManagedThreadId)
    End Sub
    Public Data(100000000) As Long
End Class

' 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
'

Açıklamalar

Bu oluşturucu LazyThreadSafetyMode.ExecutionAndPublicationisThreadSafe ile başlatılan bir Lazy<T> örneğin iş parçacığı güvenlik modu ise true; değilse modu şeklindedirLazyThreadSafetyMode.None. İş parçacığı güvenlik modu, birden çok iş parçacığı örneği başlatmaya çalıştığındaki Lazy<T> davranışı açıklar.

Modu belirtmek LazyThreadSafetyMode.PublicationOnly için veya Lazy<T>(LazyThreadSafetyMode) oluşturucuyu Lazy<T>(Func<T>, LazyThreadSafetyMode) kullanın.

tarafından valueFactory oluşan özel durumlar önbelleğe alınır. Daha fazla bilgi için sınıfına Lazy<T> veya numaralandırmaya System.Threading.LazyThreadSafetyMode bakın.

Ayrıca bkz.

Şunlara uygulanır

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

Kaynak:
Lazy.cs
Kaynak:
Lazy.cs
Kaynak:
Lazy.cs

Belirtilen başlatma işlevini ve iş parçacığı güvenliği modunu kullanan sınıfının yeni bir örneğini Lazy<T> başlatır.

public:
 Lazy(Func<T> ^ valueFactory, System::Threading::LazyThreadSafetyMode mode);
public Lazy (Func<T> valueFactory, System.Threading.LazyThreadSafetyMode mode);
new Lazy<'T> : Func<'T> * System.Threading.LazyThreadSafetyMode -> Lazy<'T>
Public Sub New (valueFactory As Func(Of T), mode As LazyThreadSafetyMode)

Parametreler

valueFactory
Func<T>

Gerektiğinde lazily initialized değerini üretmek için çağrılan temsilci.

mode
LazyThreadSafetyMode

İş parçacığı güvenlik modunu belirten numaralandırma değerlerinden biri.

Özel durumlar

mode geçersiz bir değer içeriyor.

valueFactory, null değeridir.

Örnekler

Aşağıdaki örnek, birden çok iş parçacığının nesne oluşturmak için yavaş bir başlatıcı oluşturmasına olanak tanıyan bir yavaş başlatıcı oluşturmak için bu oluşturucunun kullanımını gösterir. Birden çok iş parçacığı örnek oluşturmada başarılı olabilir, ancak tüm iş parçacıkları önce oluşturulan örneği kullanır. Buna ek olarak, örnek belirttiğinizde LazyThreadSafetyMode.PublicationOnlyözel durumların hiçbir zaman önbelleğe alınmadığını gösterir. Başlatma işlemi, lazily oluşturulan türün parametresiz oluşturucu tarafından yerine bir işlev tarafından gerçekleştirilse bile.

Not

Bu oluşturucunun tek iş parçacıklı senaryolarda (için belirterek LazyThreadSafetyMode.None ) nasıl kullanılacağını gösteren bir örnek için modeoluşturucuya Lazy<T>(Boolean) bakın. Çok iş parçacıklı senaryolarda (için belirterek LazyThreadSafetyMode.ExecutionAndPublication ) yarış koşulları yerine kilitleme sağlamak için bu oluşturucunun nasıl kullanılacağını gösteren bir örnek için mode, oluşturucuya Lazy<T>() bakın.

Örnek, birkaç iş parçacığından herhangi biri tarafından yavaş başlatılacak bir LargeObject sınıf tanımlar. Kodun dört önemli bölümü başlatıcının oluşturulmasını, gerçek başlatmayı, başlatma işlevini ve sınıfın oluşturucu ve sonlandırıcısını LargeObject gösterir. Yöntemin Main başında, örnek yavaş başlatma LargeObjectişlemi gerçekleştiren nesnesini oluştururLazy<T>:

lazyLargeObject = new Lazy<LargeObject>(InitLargeObject,
                             LazyThreadSafetyMode.PublicationOnly);
let lazyLargeObject = Lazy<LargeObject>(initLargeObject, LazyThreadSafetyMode.PublicationOnly)
lazyLargeObject = New Lazy(Of LargeObject)(AddressOf InitLargeObject, _
     LazyThreadSafetyMode.PublicationOnly)

Yavaş başlatıcı başlatmayı gerçekleştirmek için bir işlev kullanır. Bu durumda, sınıfı için LargeObject parametresiz oluşturucu olmadığından bir işlev gereklidir.

Örnek, bir ManualResetEvent nesne üzerinde blok oluşturan ve başlatan üç iş parçacığı oluşturur ve başlatır, böylece örnek iş parçacıklarının tümünü aynı anda serbest bırakabilir. ThreadProc Üç iş parçacığı tarafından kullanılan yönteminde özelliğini çağırmak Value örneği oluştururLargeObject:

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);
}
try
    let 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 (fun () -> 
        large.Data[0] <- Thread.CurrentThread.ManagedThreadId
        printfn $"LargeObject was initialized by thread {large.InitializedBy} last used by thread {large.Data[0]}.")
with :? ApplicationException as ex ->
    printfn $"ApplicationException: {ex.Message}"
Dim large As LargeObject = Nothing
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.)
    SyncLock 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))
    End SyncLock
Catch ex As ApplicationException
    Console.WriteLine("ApplicationException: {0}", ex.Message)
End Try

Kodun üçüncü anahtar bölümünde, örneği oluşturmak için gecikmeli başlatma işlevi çağrılır LargeObject . İşlev ilk kez çağrıldığında bir özel durum oluşturur:

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);
}
let mutable instanceCount = 0
let initLargeObject () =
    if 1 = Interlocked.Increment &instanceCount then
        raise (ApplicationException $"Lazy initialization function failed on thread {Thread.CurrentThread.ManagedThreadId}.")
    LargeObject Thread.CurrentThread.ManagedThreadId
Private Shared instanceCount As Integer = 0
Private Shared Function InitLargeObject() As LargeObject
    If 1 = Interlocked.Increment(instanceCount) Then
        Throw New ApplicationException( _
            "Lazy initialization function failed on thread " & _
            Thread.CurrentThread.ManagedThreadId & ".")
    End If
    Return New LargeObject(Thread.CurrentThread.ManagedThreadId)
End Function

Diğer LazyThreadSafetyMode tüm ayarlarda, başlatma işlevinde işlenmeyen bir özel durum önbelleğe alınır. Ancak, LazyThreadSafetyMode.PublicationOnly özel durum önbelleğini gizler. Örnekten alınan çıktı, nesneyi başlatmaya yönelik sonraki bir girişimin başarılı olduğunu gösterir.

Not

Özel durum iletisi genellikle diğer iş parçacıklarının nesneyi başarıyla başlatdığını belirten iletilerden sonra görüntülenir. Bunun nedeni, özel durumun atılması ve yakalanmasının neden olduğu gecikmedir.

Örneğin oluşturucusunun belirttiğindenLazyThreadSafetyMode.PublicationOnly, üç iş parçacığının Lazy<T> da örnek oluşturmasına LargeObject izin verilir. Örnek, oluşturucuda ve sınıfın sonlandırıcısında LargeObject konsol iletilerini görüntüleyerek bunu gösterir:

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);
}
type LargeObject(initBy) =
    do
        printfn $"Constructor: Instance initializing on thread {initBy}"

    override _.Finalize() =
        printfn $"Finalizer: Instance was initialized on {initBy}"
Public Sub New(ByVal initializedBy As Integer)
    initBy = initializedBy
    Console.WriteLine("Constructor: Instance initializing on thread {0}", initBy)
End Sub

Protected Overrides Sub Finalize()
    Console.WriteLine("Finalizer: Instance was initialized on {0}", initBy)
End Sub

Lazy<T> nesnesi, tüm iş parçacıkları tarafından yalnızca bir örneğin kullanılmasını sağlar (başlatma işlevinin özel durum oluşturduğu iş parçacığı dışında). Örnekteki çıktı bunu gösterir.

Not

Kolaylık olması için, bu örnekte genel bir örneği Lazy<T>kullanılır ve tüm yöntemler (Shared Visual Basic'te) şeklindedir static . Bunlar yavaş başlatmanın kullanılması için bir gereksinim değildir.

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
 */
open System
open System.Threading

type LargeObject(initBy) =
    do
        printfn $"Constructor: Instance initializing on thread {initBy}"

    override _.Finalize() =
        printfn $"Finalizer: Instance was initialized on {initBy}"
    member _.InitializedBy = initBy
    member val Data = Array.zeroCreate<int64> 100000000 with get

// Factory function for lazy initialization.
let mutable instanceCount = 0
let initLargeObject () =
    if 1 = Interlocked.Increment &instanceCount then
        raise (ApplicationException $"Lazy initialization function failed on thread {Thread.CurrentThread.ManagedThreadId}.")
    LargeObject Thread.CurrentThread.ManagedThreadId

// The lazy initializer is created here. LargeObject is not created until the
// ThreadProc method executes.
let lazyLargeObject = Lazy<LargeObject>(initLargeObject, LazyThreadSafetyMode.PublicationOnly)

let threadProc (state: obj) =
    // Wait for the signal.
    let waitForStart = state :?> ManualResetEvent
    waitForStart.WaitOne() |> ignore

    try
        let 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 (fun () -> 
            large.Data[0] <- Thread.CurrentThread.ManagedThreadId
            printfn $"LargeObject was initialized by thread {large.InitializedBy} last used by thread {large.Data[0]}.")
    with :? ApplicationException as ex ->
        printfn $"ApplicationException: {ex.Message}"

// Create and start 3 threads, passing the same blocking event to all of them.
let startingGate = new ManualResetEvent false
let threads = 
    [| Thread(ParameterizedThreadStart threadProc); Thread(ParameterizedThreadStart threadProc); Thread(ParameterizedThreadStart threadProc) |]
for t in threads do
    t.Start startingGate

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

// Wait for all 3 threads to finish. (The order doesn't matter.)
for t in threads do
    t.Join()

printfn "\nThreads are complete. Running GC.Collect() to reclaim extra instances."

GC.Collect()

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

printfn "\nNote that only one instance of LargeObject was used."
printfn "Press Enter to end the program"
stdin.ReadLine() |> ignore

// 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
Imports System.Threading

Friend Class Program
    Private Shared lazyLargeObject As Lazy(Of LargeObject) = Nothing

    ' Factory function for lazy initialization.
    Private Shared instanceCount As Integer = 0
    Private Shared Function InitLargeObject() As LargeObject
        If 1 = Interlocked.Increment(instanceCount) Then
            Throw New ApplicationException( _
                "Lazy initialization function failed on thread " & _
                Thread.CurrentThread.ManagedThreadId & ".")
        End If
        Return New LargeObject(Thread.CurrentThread.ManagedThreadId)
    End Function

    Shared Sub Main()
        ' The lazy initializer is created here. LargeObject is not created until the 
        ' ThreadProc method executes.
        lazyLargeObject = New Lazy(Of LargeObject)(AddressOf InitLargeObject, _
             LazyThreadSafetyMode.PublicationOnly)


        ' Create and start 3 threads, passing the same blocking event to all of them.
        Dim startingGate As New ManualResetEvent(False)
        Dim threads() As Thread = { _
            New Thread(AddressOf ThreadProc), _
            New Thread(AddressOf ThreadProc), _
            New Thread(AddressOf ThreadProc) _
        }
        For Each t As Thread In threads
            t.Start(startingGate)
        Next t

        ' 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.)
        For Each t As Thread In threads
            t.Join()
        Next t

        Console.WriteLine(vbCrLf & _
            "Threads are complete. Running GC.Collect() to reclaim extra instances.")

        GC.Collect()

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

        Console.WriteLine(vbCrLf & "Note that only one instance of LargeObject was used.")
        Console.WriteLine("Press Enter to end the program")
        Console.ReadLine()
    End Sub


    Private Shared Sub ThreadProc(ByVal state As Object)
        ' Wait for the signal.
        Dim waitForStart As ManualResetEvent = CType(state, ManualResetEvent)
        waitForStart.WaitOne()

        Dim large As LargeObject = Nothing
        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.)
            SyncLock 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))
            End SyncLock
        Catch ex As ApplicationException
            Console.WriteLine("ApplicationException: {0}", ex.Message)
        End Try
    End Sub
End Class

Friend Class LargeObject
    Private initBy As Integer = -1
    Public ReadOnly Property InitializedBy() As Integer
        Get
            Return initBy
        End Get
    End Property

    Public Sub New(ByVal initializedBy As Integer)
        initBy = initializedBy
        Console.WriteLine("Constructor: Instance initializing on thread {0}", initBy)
    End Sub

    Protected Overrides Sub Finalize()
        Console.WriteLine("Finalizer: Instance was initialized on {0}", initBy)
    End Sub

    Public Data(99999999) As Long
End Class

' This example produces output similar to the following:
'
'Constructor: Instance initializing on thread 4
'ApplicationException: Lazy initialization function failed 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.
'
'Threads are complete. Running GC.Collect() to reclaim extra instances.
'Finalizer: Instance was initialized on 5
'
'Note that only one instance of LargeObject was used.
'Press Enter to end the program
'
'Finalizer: Instance was initialized on 4
'

Açıklamalar

Bir Lazy<T> örneğin iş parçacığı güvenlik modu, birden çok iş parçacığı örneği başlatmaya çalıştığında oluşan Lazy<T> davranışı açıklar.

tarafından valueFactory oluşan özel durumlar, dışında modeLazyThreadSafetyMode.PublicationOnlyönbelleğe alınır. Daha fazla bilgi için sınıfına Lazy<T> veya numaralandırmaya System.Threading.LazyThreadSafetyMode bakın.

Ayrıca bkz.

Şunlara uygulanır