2011-08-24 20 views
7

मेरे पास निम्न कोड है जिसे एक ही सेकंड में एकाधिक वेब-अनुरोधों के माध्यम से बुलाया जा सकता है। इस प्रकार, मैं डेटाबेस को मारने वाला दूसरा + अनुरोध नहीं चाहता, लेकिन पहले तक इंतजार कर रहा हूं।क्या इस सी # कोड को आलसी <T> कक्षा का उपयोग करने के लिए दोबारा उपयोग किया जाना चाहिए?

क्या मुझे इसके बजाय Lazy<T> कीवर्ड कक्षा का उपयोग करने के लिए इसे पुन: सक्रिय करना चाहिए? यदि कोड के Lazy<T> कोड के 10 कॉल एक ही समय में होते हैं, तो उनमें से 9 कॉल करने वाले पहले व्यक्ति को पूरा करने की प्रतीक्षा करें?

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 
} 
+2

'आलसी ' कोई कीवर्ड नहीं है। – BoltClock

+0

तो फिर इसे क्या कहा जाता है? –

+0

इसे बस एक प्रकार कहा जाता है। अधिक विशेष रूप से, यह एक वर्ग है। – BoltClock

उत्तर

12

हाँ आप MSDN से Lazy<T>

उपयोग कर सकते हैं:

डिफ़ॉल्ट रूप से, Lazy वस्तुओं धागा सुरक्षित हैं। यही है, अगर कन्स्ट्रक्टर थ्रेड सुरक्षा की तरह निर्दिष्ट नहीं करता है, तो आलसी ऑब्जेक्ट्स जो इसे बनाता है वह थ्रेड-सुरक्षित हैं। बहुप्रचारित परिदृश्यों में, थ्रेड-सुरक्षित Lazy ऑब्जेक्ट की वैल्यू प्रॉपर्टी तक पहुंचने के लिए पहला थ्रेड सभी थ्रेड, और पर सभी बाद के एक्सेसों के लिए प्रारंभ करता है, सभी थ्रेड एक ही डेटा साझा करते हैं। इसलिए, इससे कोई फर्क नहीं पड़ता कि धागा वस्तु को आरंभ करता है, और दौड़ की स्थिति सौम्य होती है। इसकी एक .NET फ़्रेमवर्क वर्ग कि आलसी आरंभीकरण के लिए अक्सर आवश्यक उपयोग के मामले formalizes और बॉक्स से बाहर इस प्रदान करता है ताकि आप इसे "मैन्युअल" ऐसा करने के लिए नहीं है -

और हाँ, यह एक कीवर्ड है।

8

जैसा कि @ ब्रोकनग्लस ने बताया कि यह सुरक्षित है। लेकिन मैं विरोध नहीं कर सका और एक परीक्षण करना था ...

केवल एक धागा आईडी छपा है ...

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(); 
} 

लेकिन, जो एक तेज है? परिणाम मुझे मिल गया ...

कोड निष्पादित से 100 गुना

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

कोड निष्पादित 100000000 बार

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

टेस्ट कोड:

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

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

टेस्ट विधि:

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")); 
} 
+0

बहुत बढ़िया काम @ ब्रूनोएलएम :) –