Xerx and I have been playing around with using Lazy<T> for one-time, asynchronous initialisation of values, and we stumbled across the various threading options that Lazy<T> supports. After puzzling over the documentation for a while I thought it was probably easier just to run a few examples.

Here’s the test case we’ll use to demonstrate these options:

The func used to initialise lazy value takes at least 100ms to run, and increments and returns a counter value i. We then try and access the lazy value directly, and while the initialisation code is running, we also try and access it from an async Task<T>. We’ll then output what each method returns, as well as the final value of the counter i.

The default thread safety mode when you call new Lazy<T>(func), or new Lazy<T>(func, true), is LazyThreadSafetyMode.ExecutionAndPublication. Running in this mode ensures the initialisation code only runs once:

direct lazy value access
getting lazy value
v: 0, task: 0, i: 1

Both the task and direct access agree on the initialised value of 0, and the i counter has only incremented once to give 1.

## Safe on publication

If we now update the safety mode to LazyThreadSafetyMode.PublicationOnly, we get this:

direct lazy value access
getting lazy value
getting lazy value
v: 0, task: 0, i: 2

Here we can see the initialisation code has run twice; there are two "getting lazy value" messages, and i has been incremented twice to 2. Both the task and direct access agree on the value 0 though. So the first initialisation value returned wins.

## All bets are off

Finally, LazyThreadSafetyMode.None (which is what we get when we call new Lazy<T>(func, false)) gives this output:

direct lazy value access
getting lazy value

System.AggregateException : One or more errors occurred.
----> System.InvalidOperationException : ValueFactory attempted to access the Value property of this instance.

This option provides no thread safety, so trying to access or set the value concurrently fails with an exception.

## Summary

These options are explained in more detail on MSDN, but a quick summary is:

• ExecutionAndPublication ensures initialisation code is only executed once. This is the default.
• PublicationOnly lets multiple threads race to initialise the value, and the first one finished wins.
• None has no thread safety, and can throw exceptions on concurrent initialisation.