Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Inisialisasi tertunda dari sebuah objek berarti bahwa pembuatannya ditangguhkan sampai objek tersebut pertama kali digunakan. (Untuk topik ini, istilah inisialisasi malas dan instansiasi malas identik.) Inisialisasi malas terutama digunakan untuk meningkatkan performa, menghindari komputasi yang boros, dan mengurangi kebutuhan memori program. Berikut ini adalah skenario yang paling umum:
Jika Anda memiliki objek yang mahal untuk dibuat, dan program mungkin tidak menggunakannya. Misalnya, asumsikan bahwa Anda memiliki objek
Customerdalam memori, yang memiliki propertiOrdersberisi array besar dari objekOrderyang memerlukan koneksi database untuk diinisialisasi. Jika pengguna tidak pernah meminta untuk menampilkan Pesanan atau menggunakan data dalam komputasi, tidak ada alasan untuk menggunakan memori sistem atau siklus komputasi untuk membuatnya. Dengan menggunakanLazy<Orders>untuk mendeklarasikan objekOrdersuntuk inisialisasi malas, Anda dapat menghindari membuang-buang sumber daya sistem saat objek tidak digunakan.Jika Anda memiliki objek yang mahal untuk dibuat, dan Anda ingin menunda pembuatannya hingga setelah operasi mahal lainnya selesai. Misalnya, asumsikan bahwa program Anda memuat beberapa instans objek saat dimulai, tetapi hanya beberapa di antaranya yang diperlukan segera. Anda dapat meningkatkan performa startup program dengan menunda inisialisasi objek yang tidak diperlukan hingga objek yang diperlukan telah dibuat.
Meskipun Anda dapat menulis kode sendiri untuk inisialisasi yang lambat, sebaiknya Anda menggunakan Lazy<T>. Lazy<T> dan jenis terkaitnya juga mendukung keamanan rangkaian dan memberikan kebijakan penyebaran pengecualian yang konsisten.
Tabel berikut mencantumkan jenis-jenis yang disediakan oleh .NET Framework versi 4 untuk memungkinkan inisialisasi tertunda pada skenario yang berbeda.
| Tipe | Deskripsi |
|---|---|
| Lazy<T> | Kelas pembungkus yang menyediakan semantik inisialisasi tertunda untuk pustaka kelas atau tipe yang ditentukan pengguna. |
| ThreadLocal<T> | Menyerupai Lazy<T> kecuali bahwa ia menyediakan semantik inisialisasi malas pada basis lokalisasi thread. Setiap rangkaian memiliki akses ke nilai uniknya sendiri. |
| LazyInitializer | Menyediakan metode tingkat lanjut static (Shared dalam Visual Basic) untuk inisialisasi malas objek tanpa beban pemrosesan dari kelas. |
Inisialisasi Malas Dasar
Untuk menentukan tipe lazy-initialized, misalnya, MyType, gunakan Lazy<MyType> (Lazy(Of MyType) dalam Visual Basic), seperti yang ditunjukkan dalam contoh berikut. Jika tidak ada deleget yang diteruskan dalam konstruktor Lazy<T>, jenis yang terbungkus dibuat dengan menggunakan Activator.CreateInstance saat properti nilai pertama kali diakses. Jika jenis tidak memiliki konstruktor tanpa parameter, pengecualian runtime dilemparkan.
Dalam contoh berikut, asumsikan bahwa Orders adalah kelas yang berisi array objek Order yang diambil dari database. Objek Customer berisi instans Orders, tetapi tergantung pada tindakan pengguna, data dari objek Orders mungkin tidak diperlukan.
// Initialize by using default Lazy<T> constructor. The
// Orders array itself is not created yet.
Lazy<Orders> _orders = new();
' Initialize by using default Lazy<T> constructor. The
'Orders array itself is not created yet.
Dim _orders As Lazy(Of Orders) = New Lazy(Of Orders)()
Anda juga dapat meneruskan delegasi di konstruktor Lazy<T> yang memanggil muatan berlebih konstruktor tertentu pada jenis yang dibungkus pada waktu pembuatan, dan melakukan langkah inisialisasi lain yang diperlukan, seperti yang ditunjukkan dalam contoh berikut.
// Initialize by invoking a specific constructor on Order when Value
// property is accessed
Lazy<Orders> _orders = new(() => new Orders(100));
' Initialize by invoking a specific constructor on Order
' when Value property is accessed
Dim _orders As Lazy(Of Orders) = New Lazy(Of Orders)(Function() New Orders(100))
Setelah sebuah objek Lazy dibuat, tidak ada instans Orders yang dibuat hingga properti Value dari variabel Lazy diakses untuk pertama kalinya. Pada akses pertama, jenis yang dibungkus dibuat dan dikembalikan, dan disimpan untuk akses ke depannya.
// We need to create the array only if displayOrders is true
if (s_displayOrders == true)
{
DisplayOrders(_orders.Value.OrderData);
}
else
{
// Don't waste resources getting order data.
}
' We need to create the array only if _displayOrders is true
If _displayOrders = True Then
DisplayOrders(_orders.Value.OrderData)
Else
' Don't waste resources getting order data.
End If
Objek Lazy<T> selalu menampilkan objek atau nilai yang sama dengan yang diinisialisasi. Oleh karena itu, properti Value bersifat baca-saja. Jika Value menyimpan jenis referensi, Anda tidak dapat menetapkan objek baru ke dalamnya. (Namun, Anda dapat mengubah nilai bidang dan properti publik yang dapat diatur.) Jika Value menyimpan jenis nilai, Anda tidak dapat mengubah nilainya. Namun demikian, Anda dapat membuat variabel baru dengan memanggil konstruktor variabel lagi dengan menggunakan argumen baru.
_orders = new Lazy<Orders>(() => new Orders(10));
_orders = New Lazy(Of Orders)(Function() New Orders(10))
Instans lazy yang baru, seperti yang sebelumnya, tidak membuat instans Orders sampai properti Value-nya pertama kali diakses.
Inisialisasi Aman Utas
Secara default, objek Lazy<T> bersifat bebas rangkaian. Yakni, jika konstruktor tidak menentukan jenis keamanan thread, objek Lazy<T> yang dibuat aman terhadap thread. Dalam skenario multi-rangkaian, rangkaian pertama yang mengakses properti Value objek Lazy<T> bebas rangkaian menginisialisasinya untuk semua akses berikutnya di semua rangkaian, dan semua rangkaian berbagi data yang sama. Oleh karena itu, tidak masalah rangkaian mana yang menginisialisasi objek, dan kondisi balapan tidak berbahaya.
Catatan
Anda dapat memperluas konsistensi ini ke kondisi kesalahan dengan menggunakan penyimpanan sementara pengecualian. Untuk informasi selengkapnya, lihat bagian berikutnya, Pengecualian di Objek Tunda.
Contoh berikut menunjukkan bahwa instans Lazy<int> yang sama memiliki nilai yang sama untuk tiga rangkaian terpisah.
// Initialize the integer to the managed thread id of the
// first thread that accesses the Value property.
Lazy<int> number = new(() => Environment.CurrentManagedThreadId);
Thread t1 = new(() => Console.WriteLine($"number on t1 = {number.Value} ThreadID = {Environment.CurrentManagedThreadId}"));
t1.Start();
Thread t2 = new(() => Console.WriteLine($"number on t2 = {number.Value} ThreadID = {Environment.CurrentManagedThreadId}"));
t2.Start();
Thread t3 = new(() => Console.WriteLine($"number on t3 = {number.Value} ThreadID = {Environment.CurrentManagedThreadId}"));
t3.Start();
// Ensure that thread IDs are not recycled if the
// first thread completes before the last one starts.
t1.Join();
t2.Join();
t3.Join();
/* Sample Output:
number on t1 = 11 ThreadID = 11
number on t3 = 11 ThreadID = 13
number on t2 = 11 ThreadID = 12
Press any key to exit.
*/
' Initialize the integer to the managed thread id of the
' first thread that accesses the Value property.
Dim number As Lazy(Of Integer) = New Lazy(Of Integer)(Function()
Return Thread.CurrentThread.ManagedThreadId
End Function)
Dim t1 As New Thread(Sub()
Console.WriteLine("number on t1 = {0} threadID = {1}",
number.Value, Thread.CurrentThread.ManagedThreadId)
End Sub)
t1.Start()
Dim t2 As New Thread(Sub()
Console.WriteLine("number on t2 = {0} threadID = {1}",
number.Value, Thread.CurrentThread.ManagedThreadId)
End Sub)
t2.Start()
Dim t3 As New Thread(Sub()
Console.WriteLine("number on t3 = {0} threadID = {1}",
number.Value, Thread.CurrentThread.ManagedThreadId)
End Sub)
t3.Start()
' Ensure that thread IDs are not recycled if the
' first thread completes before the last one starts.
t1.Join()
t2.Join()
t3.Join()
' Sample Output:
' number on t1 = 11 ThreadID = 11
' number on t3 = 11 ThreadID = 13
' number on t2 = 11 ThreadID = 12
' Press any key to exit.
Jika Anda memerlukan data terpisah di setiap rangkaian, gunakan jenis ThreadLocal<T>, seperti yang dijelaskan nanti dalam topik ini.
Beberapa konstruktor Lazy<T> memiliki parameter Boolean bernama isThreadSafe yang digunakan untuk menentukan apakah properti Value akan diakses dari beberapa rangkaian. Jika Anda ingin mengakses properti hanya dari satu utas, berikan nilai false untuk mendapatkan manfaat performa yang sederhana. Jika Anda ingin mengakses properti dari beberapa thread, masukkan true untuk menginstruksikan instans Lazy<T> agar menangani race condition dengan benar di mana satu thread melempar pengecualian pada waktu inisialisasi.
Beberapa konstruktor Lazy<T> memiliki parameter LazyThreadSafetyMode bernama mode. Konstruktor ini menyediakan mode keamanan rangkaian tambahan. Tabel berikut menunjukkan bagaimana keamanan rangkaian objek Lazy<T> dipengaruhi oleh parameter konstruktor yang menentukan keamanan rangkaian. Setiap konstruktor memiliki maksimal satu parameter tersebut.
| Keamanan rangkaian objek | parameter LazyThreadSafetyModemode |
Parameter isThreadSafe Boolean |
Tidak ada parameter keamanan rangkaian |
|---|---|---|---|
| Sepenuhnya bebas rangkaian; hanya satu rangkaian pada satu waktu yang mencoba menginisialisasi nilai. | ExecutionAndPublication | true |
Ya. |
| Tidak aman untuk penggunaan bersamaan. | None | false |
Tidak berlaku. |
| Sepenuhnya aman utas; utas bersaing untuk menginisialisasi nilai. | PublicationOnly | Tidak berlaku. | Tidak berlaku. |
Seperti yang ditunjukkan tabel, menentukan LazyThreadSafetyMode.ExecutionAndPublication untuk parameter mode sama dengan menentukan true untuk parameter isThreadSafe, dan menentukan LazyThreadSafetyMode.None sama dengan menentukan false.
Untuk informasi selengkapnya tentang apa yang dimaksud dengan Execution dan Publication, lihat LazyThreadSafetyMode.
Menentukan LazyThreadSafetyMode.PublicationOnly memungkinkan beberapa rangkaian untuk mencoba menginisialisasi instans Lazy<T>. Hanya satu rangkaian yang dapat memenangkan perlombaan ini, dan semua rangkaian lainnya menerima nilai yang diinsialisasi oleh rangkaian yang berhasil. Jika pengecualian muncul pada rangkaian selama inisialisasi, rangkaian tersebut tidak menerima nilai yang ditetapkan oleh rangkaian yang berhasil. Pengecualian tidak di-cache, sehingga upaya berikutnya untuk mengakses properti Value dapat mengakibatkan inisialisasi yang berhasil. Ini berbeda dengan cara pengecualian diperlakukan dalam mode lain, yang dijelaskan di bagian berikut. Untuk informasi selengkapnya, lihat enumerasi LazyThreadSafetyMode.
Pengecualian pada Objek Lamban
Seperti yang disebutkan sebelumnya, objek Lazy<T> selalu menampilkan objek atau nilai yang sama dengan yang diinisialisasi, dan oleh karena itu properti Value bersifat baca-saja. Jika Anda mengaktifkan penyimpanan sementara pengecualian, ketidakberubahan ini juga meluas ke perilaku pengecualian. Jika objek yang diinisialisasi secara malas mengaktifkan penyimpanan pengecualian dan melemparkan pengecualian dari metode inisialisasinya saat properti Value diakses pertama kali, pengecualian yang sama akan dilemparkan pada setiap upaya berikutnya untuk mengakses properti Value. Dengan kata lain, konstruktor dari jenis yang terbungkus tidak pernah dipanggil kembali, bahkan dalam skenario multithreading. Oleh karena itu, objek Lazy<T> tidak dapat memunculkan pengecualian di satu akses dan menampilkan nilai di akses berikutnya.
Penembolokan pengecualian diaktifkan saat Anda menggunakan konstruktor jenis apa pun System.Lazy<T> yang menggunakan metode inisialisasi (parameter valueFactory); misalnya, ini diaktifkan saat Anda menggunakan konstruktor Lazy(T)(Func(T)). Jika konstruktor juga mengambil nilai LazyThreadSafetyMode (parameter mode), tentukan LazyThreadSafetyMode.ExecutionAndPublication atau LazyThreadSafetyMode.None. Mengatur metode inisialisasi memungkinkan pencachingan pengecualian untuk kedua mode ini. Metode inisialisasi bisa sangat sederhana. Misalnya, ini mungkin memanggil konstruktor tanpa parameter untuk T: new Lazy<Contents>(() => new Contents(), mode) di C#, atau New Lazy(Of Contents)(Function() New Contents()) di Visual Basic. Jika Anda menggunakan konstruktor System.Lazy<T> yang tidak menentukan metode inisialisasi, pengecualian yang ditampilkan oleh konstruktor tanpa parameter untuk T tidak di-cache. Untuk informasi selengkapnya, lihat enumerasi LazyThreadSafetyMode.
Catatan
Jika Anda membuat objek Lazy<T> dengan parameter konstruktor isThreadSafe yang diatur ke false atau parameter konstruktor mode diatur ke LazyThreadSafetyMode.None, Anda harus mengakses objek Lazy<T> dari satu rangkaian atau memberikan sinkronisasi Anda sendiri. Ini berlaku untuk semua aspek objek, termasuk penyimpanan sementara pengecualian.
Seperti yang disebutkan di bagian sebelumnya, objek Lazy<T> yang dibuat dengan menentukan LazyThreadSafetyMode.PublicationOnly memperlakukan pengecualian secara berbeda. Dengan PublicationOnly, beberapa rangkaian dapat bersaing untuk menginisialisasi instans Lazy<T>. Dalam hal ini, pengecualian tidak di-cache, dan upaya untuk mengakses properti Value dapat dilanjutkan hingga inisialisasi berhasil.
Tabel berikut merangkum cara konstruktor Lazy<T> mengontrol penyimpanan sementara pengecualian.
| Konstruktor | Mode keamanan rangkaian | Menggunakan metode inisialisasi | Pengecualian disimpan dalam cache |
|---|---|---|---|
| Malas(T)() | Aku akan menemuinya.ExecutionAndPublication | Tidak | Tidak |
| Malas(T)(Func(T)) | Aku akan menemuinya.ExecutionAndPublication | Ya | Ya |
| Malas(T)(Boolean) |
True (ExecutionAndPublication) atau false (None) |
Tidak | Tidak |
| Malas(T)(Func(T), Boolean) |
True (ExecutionAndPublication) atau false (None) |
Ya | Ya |
| Malas(T)(LazyThreadSafetyMode) | Ditentukan pengguna | Tidak | Tidak |
| Malas(T)(Func(T), LazyThreadSafetyMode) | Ditentukan pengguna | Ya | Tidak jika pengguna menentukan PublicationOnly; jika tidak, ya. |
Menerapkan Inisialisasi Properti Malas
Untuk mengimplementasikan properti publik dengan menggunakan inisialisasi malas, tentukan bidang pendukung properti sebagai Lazy<T>, dan kembalikan properti Value dari pengakses get properti.
class Customer
{
private readonly Lazy<Orders> _orders;
public string CustomerID { get; private set; }
public Customer(string id)
{
CustomerID = id;
_orders = new Lazy<Orders>(() =>
{
// You can specify any additional
// initialization steps here.
return new Orders(CustomerID);
});
}
public Orders MyOrders
{
get
{
// Orders is created on first access here.
return _orders.Value;
}
}
}
Class Customer
Private _orders As Lazy(Of Orders)
Public Shared CustomerID As String
Public Sub New(ByVal id As String)
CustomerID = id
_orders = New Lazy(Of Orders)(Function()
' You can specify additional
' initialization steps here
Return New Orders(CustomerID)
End Function)
End Sub
Public ReadOnly Property MyOrders As Orders
Get
Return _orders.Value
End Get
End Property
End Class
Properti Value bersifat baca-saja; oleh karena itu, properti yang mengeksposnya tidak memiliki pengakses set. Jika Anda memerlukan properti baca/tulis yang didukung oleh objek Lazy<T>, pengakses set harus membuat objek Lazy<T> baru dan menetapkannya ke penyimpanan cadangan. Pengakses set harus membuat ekspresi lambda yang menampilkan nilai properti baru yang diteruskan ke pengakses set, dan meneruskan ekspresi lambda tersebut ke konstruktor untuk objek Lazy<T> baru. Akses properti Value berikutnya akan menyebabkan inisialisasi Lazy<T> baru, dan setelah itu properti Value-nya akan menampilkan nilai baru yang ditetapkan ke properti. Alasan untuk pengaturan rumit ini adalah untuk mempertahankan perlindungan multithreading yang tertanam dalam Lazy<T>. Jika tidak, pengakses properti harus menyimpan cache nilai pertama yang ditampilkan oleh properti Value dan hanya memodifikasi nilai yang di-cache, dan Anda harus menulis kode yang aman untuk thread sendiri untuk melakukannya. Karena inisialisasi tambahan yang diperlukan oleh properti baca/tulis yang didukung oleh objek Lazy<T>, performa mungkin tidak dapat diterima. Selain itu, tergantung pada skenario tertentu, koordinasi tambahan mungkin diperlukan untuk menghindari kondisi balapan antara setter dan getter.
Inisialisasi Malas Rangkaian Lokal
Dalam beberapa skenario multithreading, Anda mungkin ingin memberikan data privasi masing-masing ke setiap thread. Data ini disebut data rangkaian lokal. Di .NET Framework versi 3.5 dan versi sebelumnya, Anda dapat menerapkan atribut ThreadStatic ke variabel statik untuk menjadikannya rangkaian lokal. Namun, menggunakan atribut ThreadStatic dapat menyebabkan kesalahan yang tidak kentara. Misalnya, bahkan pernyataan inisialisasi dasar akan menyebabkan variabel diinisialisasi hanya pada rangkaian pertama yang mengaksesnya, seperti yang ditunjukkan dalam contoh berikut.
[ThreadStatic]
static int s_counter = 1;
<ThreadStatic()>
Shared counter As Integer
Pada semua rangkaian lainnya, variabel akan diinsialisasi dengan menggunakan nilai defaultnya (nol). Sebagai alternatif di .NET Framework versi 4, Anda dapat menggunakan jenis System.Threading.ThreadLocal<T> untuk membuat variabel berbasis instans rangkaian lokal yang diinisialisasi di semua rangkaian oleh delegasi Action<T> yang Anda sediakan. Dalam contoh berikut, semua rangkaian yang mengakses counter akan melihat nilai awalnya sebagai 1.
ThreadLocal<int> _betterCounter = new(() => 1);
Dim betterCounter As ThreadLocal(Of Integer) = New ThreadLocal(Of Integer)(Function() 1)
ThreadLocal<T> membungkus objeknya dengan cara yang sama persis seperti Lazy<T>, dengan perbedaan penting ini:
Setiap rangkaian menginisialisasi variabel rangkaian lokal dengan menggunakan data privatnya sendiri yang tidak dapat diakses dari rangkaian lain.
Properti ThreadLocal<T>.Value bersifat baca-tulis, dan dapat dimodifikasi berulang kali. Ini dapat memengaruhi penyebaran pengecualian, misalnya, satu operasi
getdapat menampilkan pengecualian tetapi yang berikutnya berhasil menginisialisasi nilai.Jika tidak ada delegasi inisialisasi yang disediakan, ThreadLocal<T> akan menginisialisasi tipe yang dibungkusnya dengan menggunakan nilai default tipe. Dalam hal ini, ThreadLocal<T> konsisten dengan atribut ThreadStaticAttribute.
Contoh berikut menunjukkan bahwa setiap rangkaian yang mengakses instans ThreadLocal<int> mendapatkan salinan data uniknya sendiri.
// Initialize the integer to the managed thread id on a per-thread basis.
ThreadLocal<int> threadLocalNumber = new(() => Environment.CurrentManagedThreadId);
Thread t4 = new(() => Console.WriteLine($"threadLocalNumber on t4 = {threadLocalNumber.Value} ThreadID = {Environment.CurrentManagedThreadId}"));
t4.Start();
Thread t5 = new(() => Console.WriteLine($"threadLocalNumber on t5 = {threadLocalNumber.Value} ThreadID = {Environment.CurrentManagedThreadId}"));
t5.Start();
Thread t6 = new(() => Console.WriteLine($"threadLocalNumber on t6 = {threadLocalNumber.Value} ThreadID = {Environment.CurrentManagedThreadId}"));
t6.Start();
// Ensure that thread IDs are not recycled if the
// first thread completes before the last one starts.
t4.Join();
t5.Join();
t6.Join();
/* Sample Output:
threadLocalNumber on t4 = 14 ThreadID = 14
threadLocalNumber on t5 = 15 ThreadID = 15
threadLocalNumber on t6 = 16 ThreadID = 16
*/
' Initialize the integer to the managed thread id on a per-thread basis.
Dim threadLocalNumber As New ThreadLocal(Of Integer)(Function() Thread.CurrentThread.ManagedThreadId)
Dim t4 As New Thread(Sub()
Console.WriteLine("number on t4 = {0} threadID = {1}",
threadLocalNumber.Value, Thread.CurrentThread.ManagedThreadId)
End Sub)
t4.Start()
Dim t5 As New Thread(Sub()
Console.WriteLine("number on t5 = {0} threadID = {1}",
threadLocalNumber.Value, Thread.CurrentThread.ManagedThreadId)
End Sub)
t5.Start()
Dim t6 As New Thread(Sub()
Console.WriteLine("number on t6 = {0} threadID = {1}",
threadLocalNumber.Value, Thread.CurrentThread.ManagedThreadId)
End Sub)
t6.Start()
' Ensure that thread IDs are not recycled if the
' first thread completes before the last one starts.
t4.Join()
t5.Join()
t6.Join()
'Sample(Output)
' threadLocalNumber on t4 = 14 ThreadID = 14
' threadLocalNumber on t5 = 15 ThreadID = 15
' threadLocalNumber on t6 = 16 ThreadID = 16
Variabel Rangkaian Lokal dalam Parallel.For dan ForEach
Saat Anda menggunakan metode Parallel.For atau metode Parallel.ForEach untuk melakukan perulangan sumber data secara paralel, Anda dapat menggunakan muatan berlebih yang memiliki dukungan bawaan untuk data rangkaian lokal. Dalam metode ini, lokalitas rangkaian dicapai dengan menggunakan delegasi lokal untuk membuat, mengakses, dan membersihkan data. Untuk informasi selengkapnya, lihat Cara: Menulis Perulangan Paralel.For Loop dengan Variabel Rangkaian Lokal dan Cara: Menulis Perulangan Parallel.ForEach dengan Variabel Partisi-Lokal.
Menggunakan Inisialisasi Malas untuk Skenario Overhead Rendah
Dalam skenario di mana Anda harus menginisialisasi secara malas sejumlah besar objek, Anda mungkin memutuskan bahwa membungkus setiap objek dalam Lazy<T> memerlukan terlalu banyak memori atau sumber daya komputasi. Atau, Anda mungkin memiliki persyaratan ketat tentang bagaimana inisialisasi malas dipaparkan. Dalam kasus tersebut, Anda dapat menggunakan metode static (Shared dalam Visual Basic) dari kelas System.Threading.LazyInitializer untuk melakukan inisialisasi tunda setiap objek tanpa perlu membungkusnya dalam instance Lazy<T>.
Dalam contoh berikut, asumsikan bahwa, alih-alih membungkus seluruh objek Orders dalam satu objek Lazy<T>, Anda memiliki objek Order individual yang diinisialisasi secara malas hanya ketika diperlukan.
// Assume that _orders contains null values, and
// we only need to initialize them if displayOrderInfo is true
if (displayOrderInfo == true)
{
for (int i = 0; i < _orders.Length; i++)
{
// Lazily initialize the orders without wrapping them in a Lazy<T>
LazyInitializer.EnsureInitialized(ref _orders[i], () =>
{
// Returns the value that will be placed in the ref parameter.
return GetOrderForIndex(i);
});
}
}
' Assume that _orders contains null values, and
' we only need to initialize them if displayOrderInfo is true
If displayOrderInfo = True Then
For i As Integer = 0 To _orders.Length
' Lazily initialize the orders without wrapping them in a Lazy(Of T)
LazyInitializer.EnsureInitialized(_orders(i), Function()
' Returns the value that will be placed in the ref parameter.
Return GetOrderForIndex(i)
End Function)
Next
End If
Dalam contoh ini, perhatikan bahwa prosedur inisialisasi dipanggil di setiap pengulangan perulangan. Dalam skenario multi-rangkaian, rangkaian pertama yang memanggil prosedur inisialisasi adalah yang nilainya dilihat oleh semua rangkaian. Rangkaian berikutnya juga memanggil prosedur inisialisasi, tetapi hasilnya tidak digunakan. Jika kondisi balapan potensial semacam ini tidak dapat diterima, gunakan muatan berlebih LazyInitializer.EnsureInitialized yang menggunakan argumen Boolean dan objek sinkronisasi.