Lazy(Of T) Constructor (Func(Of T))
Initializes a new instance of the Lazy(Of T) class. When lazy initialization occurs, the specified initialization function is used.
Namespace: System
Assembly: mscorlib (in mscorlib.dll)
| Exception | Condition |
|---|---|
| ArgumentNullException | valueFactory is Nothing. |
An instance that is created with this constructor may be used concurrently from multiple threads.
The thread safety mode of a Lazy(Of T) instance that is initialized with this constructor is LazyThreadSafetyMode.ExecutionAndPublication. The thread safety mode describes the behavior when multiple threads try to initialize the Lazy(Of T) instance.
Exceptions that are thrown by valueFactory are cached. For more information, see the Lazy(Of T) class or the System.Threading.LazyThreadSafetyMode enumeration.
The following example demonstrates the use of this constructor to provide lazy initialization with exception caching. It also demonstrates the use of the Lazy(Of T)(Func(Of T), Boolean) constructor (specifying true for isThreadSafe) and the Lazy(Of T)(Func(Of T), LazyThreadSafetyMode) constructor (specifying LazyThreadSafetyMode.ExecutionAndPublication for mode). To switch to a different constructor, just change which constructors are commented out.
The example defines a LargeObject class that will be initialized lazily by one of several threads. The three key sections of code illustrate the creation of the initializer, the actual initialization, and the constructor of the LargeObject class, which demonstrates exception caching. At the beginning of the Main method, the example creates the thread-safe lazy initializer for LargeObject:
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)
The example creates and starts three threads. The ThreadProc method that's used by all three threads calls the Value property to get the LargeObject instance:
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
In the constructor of the LargeObject class, the third key section of code throws an exception the first time a LargeObject instance is created, but thereafter allows instance creation to occur:
When the example is run, the first thread that tries to create an instance of LargeObject fails, and the exception is caught. You might expect that the next thread would successfully create an instance, but the Lazy(Of T) object has cached the exception. Because of this, all three threads throw the exception.
Note |
|---|
For simplicity, this example uses a global instance of Lazy(Of T), and all the methods are static (Shared in Visual Basic). These are not requirements for the use of lazy initialization. |
Imports System 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 '
Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (Server Core Role not supported), Windows Server 2008 R2 (Server Core Role supported with SP1 or later; Itanium not supported)
The .NET Framework does not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.
Note