Should this C # code be reorganized instead of using the Lazy <T> class?

I have the following code that can be called through several web requests in one second. Thus, I do not want the second + query to fall into the database, but I wait until the first does.

Should I reorganize this instead of using the Lazy<T> class ? If 10 calls to the Lazy<T> code occur simultaneously, then 9 of these calls are waiting for the first completion?

 public class ThemeService : IThemeService { private static readonly object SyncLock = new object(); private static IList<Theme> _themes; private readonly IRepository<Theme> _themeRepository; <snip snip snip> #region Implementation of IThemeService public IList<Theme> Find() { if (_themes == null) { lock (SyncLock) { if (_themes == null) { // Load all the themes from the Db. _themes = _themeRepository.Find().ToList(); } } } return _themes; } <sip snip snip> #endregion } 
+7
source share
2 answers

Yes, you can use Lazy<T>

From MSDN :

By default, Lazy objects are thread safe. That is, if the constructor does not determine the type of thread safety, lazy created objects are thread safe. In multi-threaded scenarios, the first thread to access the Value property of the thread-safe Lazy object initializes it for all subsequent accesses across all threads and all threads have the same data. Therefore, it does not matter which thread initializes the object, and the race conditions are benign.

And yes, that’s not a keyword - its .NET Framework class, which formalizes a commonly used use case for lazy initialization and offers it out of the box, so you don’t need to do this “manually”.

+12
source

As @BrokenGlass pointed out, this is safe. But I could not resist and had to pass the test ...

Only one stream identifier was printed ...

 private static Lazy<int> lazyInt; // make it slow private int fib() { Thread.Sleep(1000); return 0; } public void Test() { // when run prints the thread id lazyInt = new Lazy<int>( () => { Debug.WriteLine("ID: {0} ", Thread.CurrentThread.ManagedThreadId); return fib(); }); var t1 = new Thread(() => { var x = lazyInt.Value; }); var t2 = new Thread(() => { var x = lazyInt.Value; }); var t3 = new Thread(() => { var x = lazyInt.Value; }); t1.Start(); t2.Start(); t3.Start(); t1.Join(); t2.Join(); t3.Join(); } 

But which one is faster? From the results I got ...

Code execution 100 times

 [ Lazy: 00:00:01.003 ] [ Field: 00:00:01.000 ] 

Code execution 100,000,000 times

 [ Lazy: 00:00:10.516 ] [ Field: 00:00:17.969 ] 

Test code:

 Performance.Test("Lazy", TestAmount, false, () => { var laz = lazyInt.Value; }); Performance.Test("Field", TestAmount, false, () => { var laz = FieldInt; }); 

Testing method:

 public static void Test(string name, decimal times, bool precompile, Action fn) { if (precompile) { fn(); } GC.Collect(); Thread.Sleep(2000); var sw = new Stopwatch(); sw.Start(); for (decimal i = 0; i < times; ++i) { fn(); } sw.Stop(); Console.WriteLine("[{0,15}: {1,-15}]", name, new DateTime(sw.Elapsed.Ticks).ToString("HH:mm:ss.fff")); } 
+8
source

All Articles