'स्टेटमेंट बनाम' का उपयोग करके 'अंत में प्रयास करें'


81

मुझे संपत्तियों का एक गुच्छा मिला है, जिस पर मैं पढ़ने / लिखने के ताले का उपयोग करने जा रहा हूं। मैं उन्हें या तो try finallyएक usingखंड के साथ लागू कर सकता हूं ।

में try finallyमैं ताला खोलने से पहले try, और में रिलीज होगा finally। में usingखंड, मैं एक वर्ग है जो अपने निर्माता में ताला प्राप्त कर लेता है, और उसके निपटान विधि में रिलीज पैदा करेगा।

मैं बहुत सारे स्थानों पर पढ़ने / लिखने के ताले का उपयोग कर रहा हूं, इसलिए मैं ऐसे तरीकों की तलाश कर रहा हूं जो इससे अधिक संक्षिप्त हो सकते हैं try finally। मुझे कुछ विचारों को सुनने में दिलचस्पी है कि क्यों एक तरीके की सिफारिश नहीं की जा सकती है, या एक दूसरे से बेहतर क्यों हो सकता है।

विधि 1 ( try finally):

static ReaderWriterLock rwlMyLock_m  = new ReaderWriterLock();
private DateTime dtMyDateTime_m
public DateTime MyDateTime
{
    get
    {
        rwlMyLock_m .AcquireReaderLock(0);
        try
        {
            return dtMyDateTime_m
        }
        finally
        {
            rwlMyLock_m .ReleaseReaderLock();
        }
    }
    set
    {
        rwlMyLock_m .AcquireWriterLock(0);
        try
        {
            dtMyDateTime_m = value;
        }
        finally
        {
            rwlMyLock_m .ReleaseWriterLock();
        }
    }
}

विधि 2:

static ReaderWriterLock rwlMyLock_m  = new ReaderWriterLock();
private DateTime dtMyDateTime_m
public DateTime MyDateTime
{
    get
    {
        using (new ReadLock(rwlMyLock_m))
        {
            return dtMyDateTime_m;
        }
    }
    set
    {
        using (new WriteLock(rwlMyLock_m))
        {
            dtMyDateTime_m = value;
        }
    }
}

public class ReadLock : IDisposable
{
    private ReaderWriterLock rwl;
    public ReadLock(ReaderWriterLock rwl)
    {
        this.rwl = rwl;
        rwl.AcquireReaderLock(0);
    }

    public void Dispose()
    {
        rwl.ReleaseReaderLock();
    }
}

public class WriteLock : IDisposable
{
    private ReaderWriterLock rwl;
    public WriteLock(ReaderWriterLock rwl)
    {
        this.rwl = rwl;
        rwl.AcquireWriterLock(0);
    }

    public void Dispose()
    {
        rwl.ReleaseWriterLock();
    }
}

1
जैसे पहले से ही कई उत्तरों में कहा गया है, विधि 2 बहुत अच्छी है, लेकिन हर बार जब आप लॉक का उपयोग करते हैं, तो ढेर पर कचरे से बचने के लिए, आपको रीडलॉक और राइटलॉक को संरचना में बदलना चाहिए। भले ही उपयोग करने वाला स्टेटमेंट किसी स्ट्रक्चर के आईडीसोफरोबल इंटरफेस का उपयोग करता हो, लेकिन C # बॉक्सिंग से बचने के लिए काफी चतुर है!
माइकल गेहलिंग ने

जवाबों:


95

MSDN से, स्टेटमेंट (C # संदर्भ) का उपयोग कर

उपयोग कथन यह सुनिश्चित करता है कि आप ऑब्जेक्ट पर विधियों को कॉल करते समय भी अपवाद कहते हैं। आप एक कोशिश ब्लॉक के अंदर वस्तु डालकर और फिर अंततः ब्लॉक में डिस्पोज को बुलाकर एक ही परिणाम प्राप्त कर सकते हैं; वास्तव में, यह है कि संकलक द्वारा उपयोग किए गए कथन का अनुवाद कैसे किया जाता है। कोड उदाहरण पहले संकलन समय पर निम्नलिखित कोड तक फैलता है (ऑब्जेक्ट के लिए सीमित गुंजाइश बनाने के लिए अतिरिक्त घुंघराले ब्रेस नोट करें):

{
  Font font1 = new Font("Arial", 10.0f);
  try
  {
    byte charset = font1.GdiCharSet;
  }
  finally
  {
    if (font1 != null)
      ((IDisposable)font1).Dispose();
  }
}

तो मूल रूप से, यह एक ही कोड है लेकिन एक अच्छा स्वचालित नल-चेक और आपके चर के लिए एक अतिरिक्त गुंजाइश के साथ है । प्रलेखन में यह भी कहा गया है कि यह "आईडीसॉपी वस्तु का सही उपयोग सुनिश्चित करता है" ताकि आप भविष्य में किसी भी अस्पष्ट मामलों के लिए और भी बेहतर फ्रेमवर्क समर्थन प्राप्त कर सकें।

तो विकल्प 2 के साथ जाएं।

एक दायरे के अंदर परिवर्तनशील होने के बाद जो तुरंत समाप्त हो जाता है, इसकी आवश्यकता नहीं है, एक प्लस भी है।


क्या एक संसाधन जारी करने के लिए सबसे अच्छा है जिसे बयान का उपयोग करने या पुन: उपयोग किए जाने या बाहर परम के रूप में पारित नहीं किया जा सकता है।
बजन

2
@ भजन अच्छी तरह से, आप usingउस मामले में भी क्यों विचार कर रहे हैं ? वह नहीं है जो usingके लिए है।
चक्रित

1
यही कारण है कि मैं भी उल्लेख try/catchकरता हूं क्योंकि यह try/catch/finallyब्लॉक के माध्यम से संभालने का एकमात्र तरीका है । आशा व्यक्त की usingकि यह बहुत संभाल सकता
bjan

ठीक है, हाँ, try/finallyउस मामले में आपका एकमात्र विकल्प मुझे लगता है। IMO, हालांकि, मुझे लगता है कि हमेशा ऐसे मामलों में वस्तु का जीवनकाल बनाए रखने के लिए ज़िम्मेदार कुछ कोड / टुकड़ा होना चाहिए (जहाँ डिस्पोज़ () हमेशा कहा जाना चाहिए।) यदि एक वर्ग केवल तात्कालिकता को संभालता है और किसी और को याद रखना है। इसे निपटाने के लिए मुझे लगता है कि यह एक प्रकार की बदबू आ रही है। निश्चित नहीं कि भाषा के स्तर पर कोई इसे कैसे जोड़ेगा।
चक्रित

मुझे लगता है कि "उपयोग करने" से बचने का एकमात्र कारण डिस्पोजेबल से पूरी तरह से बचना है क्योंकि यह अभी तक एक और वस्तु तात्कालिकता है जो मुझे लगता है?
डेमेट्रीस लेप्टोस

12

मैं निश्चित रूप से दूसरी विधि पसंद करता हूं। यह उपयोग के बिंदु पर अधिक संक्षिप्त है, और कम त्रुटि वाला है।

पहले मामले में किसी को कोड को संपादित करने के लिए सावधान रहना होगा कि एक्वायर (पढ़ो लिखो) लॉक कॉल और कोशिश के बीच कुछ भी न डालें।

(इस तरह के व्यक्तिगत गुणों पर एक रीड / राइट लॉक का उपयोग करना आमतौर पर हालांकि ओवरकिल होता है। वे सबसे अधिक उच्च स्तर पर लागू होते हैं। विवाद की संभावना के कारण एक साधारण लॉक अक्सर पर्याप्त होता है, क्योंकि लॉक को आयोजित किया जाता है। के लिए, एक रीड / राइट लॉक को प्राप्त करना और एक साधारण लॉक की तुलना में अधिक महंगा ऑपरेशन है)।


फेल-सेफ कैसे रहे? मुझे पता है कि एक कोशिश आखिरकार हमेशा के लिए ब्लॉक हो जाएगी, क्या कोई ऐसा तरीका है जिसे डिस्पोजल नहीं कहा जाएगा?
जेरेमी

1
नहीं, उपयोग कथन आवश्यक रूप से कोशिश / अंत में पैटर्न के लिए अनिवार्य रूप से चीनी है।
ब्लेयर कॉनराड

उपयोग करने वाला मॉडल यह सुनिश्चित करता है कि वस्तु को हमेशा निपटाया जाएगा।
नाथेन सिल्वर

यदि आप परावर्तक का उपयोग करते हैं, तो आप देखेंगे कि उपयोग करने वाले ब्लॉक को संकलक द्वारा एक कोशिश में अनुवादित किया जाता है ... अंत में निर्माण होता है, इसलिए IL स्तर पर वे बराबर होते हैं। The उपयोग करना ’केवल वाक्यगत चीनी है।
रॉब वॉकर

^ ^ याद रखें कि संभावित परिदृश्य हैं जहां अंत में नहीं कहा जाता है। उदाहरण के लिए बिजली कटौती। ;)
Quibblesome

8

इस संभावना पर विचार करें कि दोनों समाधान खराब हैं क्योंकि वे अपवादों को मुखौटा बनाते हैं

एक के tryबिना catchस्पष्ट रूप से एक बुरा विचार होना चाहिए; एमएसडीएन देखें कि क्यों usingबयान इसी तरह खतरनाक है।

ध्यान दें कि Microsoft अब ReaderWriterLock के बजाय ReaderWriterLockSlim की सिफारिश करता है ।

अंत में, ध्यान दें कि इन उदाहरणों से बचने के लिए Microsoft उदाहरण दो ट्राइ-कैच ब्लॉक का उपयोग करता है

try
{
    try
    {
         //Reader-writer lock stuff
    }
    finally
    {
         //Release lock
    }
 }
 catch(Exception ex)
 {
    //Do something with exception
 }

एक सरल, सुसंगत, स्वच्छ समाधान एक अच्छा लक्ष्य है, लेकिन यह मानते हुए कि आप सिर्फ उपयोग नहीं कर सकते lock(this){return mydateetc;}, आप दृष्टिकोण पर पुनर्विचार कर सकते हैं; अधिक जानकारी के साथ मुझे यकीन है कि स्टैक ओवरफ्लो मदद कर सकता है ;-)


2
एक कोशिश अंत में जरूरी नहीं कि अपवाद के रूप में हो। मेरे उदाहरण में, लॉक को एक्वायर्ड किया जाता है, फिर यदि किसी अपवाद को दायरे में फेंक दिया जाता है, तो लॉक को मुक्त कर दिया जाएगा, लेकिन अपवाद अभी भी बुलबुला होगा।
जेरेमी

1
@ जेरेमी: यदि आपका अंत में एक अपवाद को फेंकता है, तो यह आपके प्रयास ब्लॉक में फेंके गए अपवाद का सामना करेगा - जो कि एमएसडीएन लेख कह रहा था, सिंटैक्स का उपयोग करने के साथ (समान) समस्या थी
स्टीवन ए। लोव

3
यह अपवाद का सामना नहीं करेगा, यह अपवाद को उसी तरह से बदल देगा जैसे आप करेंगे।
जॉन हैना

5

मैं व्यक्तिगत रूप से जितनी बार संभव हो उतनी बार C # "" कथन का उपयोग करता हूं, लेकिन कुछ विशिष्ट चीजें हैं जो मैं उल्लेखित संभावित मुद्दों से बचने के लिए इसके साथ करता हूं। उदाहरण देकर स्पष्ट करने के लिए:

void doSomething()
{
    using (CustomResource aResource = new CustomResource())
    {
        using (CustomThingy aThingy = new CustomThingy(aResource))
        {
            doSomething(aThingy);
        }
    }
}

void doSomething(CustomThingy theThingy)
{
    try
    {
        // play with theThingy, which might result in exceptions
    }
    catch (SomeException aException)
    {
        // resolve aException somehow
    }
}

ध्यान दें कि मैं "प्रयोग" कथन को एक विधि में और वस्तु का उपयोग किसी अन्य विधि में "कोशिश" / "पकड़" ब्लॉक के साथ अलग करता हूं। मैं संबंधित वस्तुओं के लिए इस तरह के बयानों का उपयोग करते हुए कई "घोंसला" कर सकता हूं (मैं कभी-कभी अपने उत्पादन कोड में तीन या चार गहरा जाता हूं)।

Dispose()इन कस्टम IDisposableकक्षाओं के लिए मेरे तरीकों में , मैं अपवादों को पकड़ता हूं (लेकिन त्रुटियाँ नहीं) और उन्हें लॉग (लॉग 4नेट का उपयोग करके)। मुझे कभी भी ऐसी स्थिति का सामना नहीं करना पड़ा जहां उन अपवादों में से कोई भी संभवतः मेरे प्रसंस्करण को प्रभावित कर सकता है। संभावित त्रुटियों, हमेशा की तरह, कॉल स्टैक को प्रचारित करने की अनुमति दी जाती है और आमतौर पर एक उपयुक्त संदेश (त्रुटि और स्टैक ट्रेस) लॉग के साथ प्रसंस्करण को समाप्त करता है।

अगर मुझे किसी तरह की स्थिति का सामना करना पड़ता है जहां एक महत्वपूर्ण अपवाद हो सकता है Dispose(), तो मैं उस स्थिति के लिए फिर से डिज़ाइन करूंगा। सच कहूं, मुझे संदेह है कि कभी भी होगा।

इस बीच, "उपयोग" के दायरे और सफाई के फायदे इसे मेरी सबसे पसंदीदा C # सुविधाओं में से एक बनाते हैं। वैसे, मैं अपनी प्राथमिक भाषाओं के रूप में जावा, सी #, और पायथन में काम करता हूं, जिसमें बहुत सारे अन्य लोग यहां और वहां फेंके गए हैं, और "उपयोग करना" मेरी सबसे पसंदीदा भाषा विशेषताओं में से एक है, क्योंकि यह एक व्यावहारिक, हर रोज का कार्य है। ।


टिप, कोड पठनीयता के लिए: आंतरिक "उपयोग" को छोड़कर घुंघराले ब्रेसिज़ न होने से उपयोग बयानों को संरेखित और संपीड़ित करें।
बेंट ट्रानबर्ग

4

मुझे तीसरा विकल्प पसंद है

private object _myDateTimeLock = new object();
private DateTime _myDateTime;

public DateTime MyDateTime{
  get{
    lock(_myDateTimeLock){return _myDateTime;}
  }
  set{
    lock(_myDateTimeLock){_myDateTime = value;}
  }
}

आपके दो विकल्पों में से, दूसरा विकल्प सबसे साफ है और यह समझना आसान है कि क्या हो रहा है।


लॉक स्टेटमेंट उसी तरह से काम नहीं करता है जैसे रीडरवर्टलॉक करता है।
चक्र

@ आचार्य: नहीं, लेकिन जब तक आप नहीं जानते कि वास्तव में ताला विवाद है, तो वे अधिक प्रदर्शन करने की संभावना रखते हैं।
माइकल बूर

सच है, लेकिन आपको हमेशा पहले स्मैक लॉक के लिए जाना चाहिए। सबबी का प्रश्न प्रदर्शन के मुद्दों या आवश्यकताओं के बारे में कुछ भी नहीं बताता है जो लॉक की अनुमति नहीं देगा। इसलिए कोशिश करने और सुस्त होने का कोई कारण नहीं है। बस इसे लॉक करें और रॉक करें।

4

"संपत्ति का गुच्छा" और संपत्ति पाने वाले और सेटर स्तर पर ताला लगाना गलत लगता है। आपका लॉकिंग बहुत ज्यादा बारीक है। अधिकांश विशिष्ट ऑब्जेक्ट उपयोग में, आप यह सुनिश्चित करना चाहेंगे कि आपने एक ही समय में एक से अधिक संपत्ति तक पहुंचने के लिए लॉक का अधिग्रहण किया हो । आपका विशिष्ट मामला अलग हो सकता है, लेकिन मुझे इस पर संदेह है।

वैसे भी, जब आप संपत्ति का उपयोग करते हैं तो लॉक को प्राप्त करना संपत्ति के लॉकिंग कोड की मात्रा पर काफी कटौती करेगा, जिसे आपको लिखना होगा।


हां, मैं आपकी बात का बचाव करता हूं। मेरे अधिकांश गुण वास्तव में बूल्स, इनट्स हैं, जिन्हें मुझे लॉक करने की आवश्यकता नहीं है क्योंकि उन्हें परमाणु होना चाहिए। कुछ डेटाइम, स्ट्रिंग हैं जिन्हें मैं लॉक करना चाहता हूं। क्योंकि अल्पसंख्यक को ताले की आवश्यकता होगी, इसलिए मैंने इसे संपत्ति पर लगाने के लिए सबसे अच्छा प्रयास किया
जेरेमी

4

DRY कहता है: दूसरा उपाय। पहला समाधान लॉक का उपयोग करने के तर्क को दोहराता है, जबकि दूसरा नहीं करता है।


1

कोशिश / कैच ब्लॉक आमतौर पर अपवाद से निपटने के लिए होते हैं, जबकि ब्लॉक का उपयोग यह सुनिश्चित करने के लिए किया जाता है कि वस्तु का निपटान किया गया है।

पढ़ने / लिखने के लिए ताला / कोशिश सबसे उपयोगी हो सकती है, लेकिन आप दोनों का उपयोग भी कर सकते हैं, जैसे:

using (obj)
{
  try { }
  catch { }
}

ताकि आप स्पष्ट रूप से अपने आईडीसॉफ़लेट इंटरफ़ेस को कॉल कर सकें और साथ ही साथ संक्षिप्त हैंडलिंग संक्षिप्त बना सकें।


0

मुझे लगता है कि विधि 2 बेहतर होगी।

  • आपके गुणों में सरल और अधिक पठनीय कोड।
  • कम त्रुटि-प्रवणता क्योंकि लॉकिंग कोड को कई बार फिर से लिखना नहीं पड़ता है।

0

जबकि मैं उपरोक्त टिप्पणियों में से कई के साथ सहमत हूं, जिसमें लॉक की ग्रैन्युलैरिटी और संदिग्ध अपवाद हैंडलिंग शामिल है, प्रश्न दृष्टिकोण में से एक है। मैं आपको एक बड़ा कारण देता हूं कि मैं कोशिश क्यों {} अंत में मॉडल ... अमूर्तता का उपयोग करना पसंद करता हूं।

मेरे पास एक अपवाद के समान एक मॉडल है। मैंने एक आधार इंटरफ़ेस ILock को परिभाषित किया और इसमें मैंने एक विधि प्रदान की जिसे एक्वायर () कहा जाता है। एक्वियर () विधि ने आईडीसॉर्पोरेट वस्तु को लौटा दिया और परिणामस्वरूप इसका मतलब है कि जब तक मैं जिस वस्तु के साथ काम कर रहा हूं वह टाइप ILock की है कि इसका उपयोग लॉकिंग स्कोप करने के लिए किया जा सकता है। यह महत्वपूर्ण क्यों है?

हम कई अलग-अलग लॉकिंग तंत्रों और व्यवहारों से निपटते हैं। आपके लॉक ऑब्जेक्ट में एक विशिष्ट टाइमआउट हो सकता है जो नियोजित करता है। आपका लॉक कार्यान्वयन मॉनिटर लॉक, रीडर लॉक, लेखक लॉक या स्पिन लॉक हो सकता है। हालांकि, फोन करने वाले के दृष्टिकोण से यह सब अप्रासंगिक है, वे इस बात की परवाह करते हैं कि संसाधन को लॉक करने का अनुबंध सम्मानित किया गया है और यह ताला इसे लागू करने के अनुरूप है।

interface ILock {
    IDisposable Acquire();
}

class MonitorLock : ILock {
    IDisposable Acquire() { ... acquire the lock for real ... }
}

मुझे आपका मॉडल पसंद है, लेकिन मैं कॉलर से लॉक मैकेनिक को छिपाने पर विचार करूंगा। FWIW, मैंने कोशिश की तकनीक के ओवरहेड बनाम कोशिश-आखिर में मापा है और डिस्पोजेबल ऑब्जेक्ट को आवंटित करने के ओवरहेड में 2-3% प्रदर्शन ओवरहेड के बीच होगा।


0

मुझे आश्चर्य है कि किसी ने भी कोशिश नहीं की है कि आखिरकार अनाम कार्यों में संलग्न होने का सुझाव दिया गया है। जिस तरह से स्टेटमेंट का उपयोग करके कक्षाओं को इंस्टेंटिअटिंग और डिस्पोज करने की तकनीक दी जाती है, इससे लॉकिंग एक ही स्थान पर रहती है। मैं इसे खुद ही पसंद करता हूं क्योंकि मैं "डिस्पोज़" शब्द की तुलना में "आखिरकार" शब्द पढ़ता हूं जब मैं एक ताला जारी करने के बारे में सोच रहा होता हूं।

class StackOTest
{
    private delegate DateTime ReadLockMethod();
    private delegate void WriteLockMethod();

    static ReaderWriterLock rwlMyLock_m  = new ReaderWriterLock();
    private DateTime dtMyDateTime_m;
    public DateTime MyDateTime
    {
        get
        {
            return ReadLockedMethod(
                rwlMyLock_m,
                delegate () { return dtMyDateTime_m; }
            );
        }
        set
        {
            WriteLockedMethod(
                rwlMyLock_m,
                delegate () { dtMyDateTime_m = value; }
            );
        }
    }

    private static DateTime ReadLockedMethod(
        ReaderWriterLock rwl,
        ReadLockMethod method
    )
    {
        rwl.AcquireReaderLock(0);
        try
        {
            return method();
        }
        finally
        {
            rwl.ReleaseReaderLock();
        }
    }

    private static void WriteLockedMethod(
        ReaderWriterLock rwl,
        WriteLockMethod method
    )
    {
        rwl.AcquireWriterLock(0);
        try
        {
            method();
        }
        finally
        {
            rwl.ReleaseWriterLock();
        }
    }
}

0

SoftwareJedi, मेरा कोई खाता नहीं है, इसलिए मैं अपने उत्तरों को संपादित नहीं कर सकता।

किसी भी स्थिति में, पिछले संस्करण सामान्य प्रयोजन के उपयोग के लिए वास्तव में अच्छा नहीं था क्योंकि रीड लॉक को हमेशा रिटर्न वैल्यू की आवश्यकता होती है। यह ठीक करता है:

class StackOTest
{
    static ReaderWriterLock rwlMyLock_m  = new ReaderWriterLock();
    private DateTime dtMyDateTime_m;
    public DateTime MyDateTime
    {
        get
        {
            DateTime retval = default(DateTime);
            ReadLockedMethod(
                delegate () { retval = dtMyDateTime_m; }
            );
            return retval;
        }
        set
        {
            WriteLockedMethod(
                delegate () { dtMyDateTime_m = value; }
            );
        }
    }

    private void ReadLockedMethod(Action method)
    {
        rwlMyLock_m.AcquireReaderLock(0);
        try
        {
            method();
        }
        finally
        {
            rwlMyLock_m.ReleaseReaderLock();
        }
    }

    private void WriteLockedMethod(Action method)
    {
        rwlMyLock_m.AcquireWriterLock(0);
        try
        {
            method();
        }
        finally
        {
            rwlMyLock_m.ReleaseWriterLock();
        }
    }
}

0

निम्नलिखित ReaderWriterLockSlim वर्ग के लिए विस्तार विधियाँ बनाता है जो आपको निम्न कार्य करने की अनुमति देता है:

var rwlock = new ReaderWriterLockSlim();
using (var l = rwlock.ReadLock())
{
     // read data
}
using (var l = rwlock.WriteLock())
{
    // write data
}

यहाँ कोड है:

static class ReaderWriterLockExtensions() {
    /// <summary>
    /// Allows you to enter and exit a read lock with a using statement
    /// </summary>
    /// <param name="readerWriterLockSlim">The lock</param>
    /// <returns>A new object that will ExitReadLock on dispose</returns>
    public static OnDispose ReadLock(this ReaderWriterLockSlim readerWriterLockSlim)
    {
        // Enter the read lock
        readerWriterLockSlim.EnterReadLock();
        // Setup the ExitReadLock to be called at the end of the using block
        return new OnDispose(() => readerWriterLockSlim.ExitReadLock());
    }
    /// <summary>
    /// Allows you to enter and exit a write lock with a using statement
    /// </summary>
    /// <param name="readerWriterLockSlim">The lock</param>
    /// <returns>A new object that will ExitWriteLock on dispose</returns>
    public static OnDispose WriteLock(this ReaderWriterLockSlim rwlock)
    {
        // Enter the write lock
        rwlock.EnterWriteLock();
        // Setup the ExitWriteLock to be called at the end of the using block
        return new OnDispose(() => rwlock.ExitWriteLock());
    }
}

/// <summary>
/// Calls the finished action on dispose.  For use with a using statement.
/// </summary>
public class OnDispose : IDisposable
{
    Action _finished;

    public OnDispose(Action finished) 
    {
        _finished = finished;
    }

    public void Dispose()
    {
        _finished();
    }
}

0

वास्तव में आपके पहले उदाहरण में, समाधानों को तुलनीय बनाने के लिए, आप IDisposableवहां भी लागू करेंगे। तब आप Dispose()से कॉल करेंगेfinally सीधे लॉक जारी करने के बजाय ब्लॉक ।

फिर आप "सेब से सेब" कार्यान्वयन (और एमएसआईएल) -वाइज़ (एमएसआईएल दोनों समाधानों के लिए समान होंगे) होंगे। यह अभी भी usingजोड़ा स्कूपिंग के कारण उपयोग करने के लिए एक अच्छा विचार है और क्योंकि फ्रेमवर्क उचित उपयोग सुनिश्चित करेगा IDisposable(यदि आप IDisposableखुद को लागू कर रहे हैं तो बाद में कम लाभकारी हो )।


-1

मुझे मूर्ख। वहाँ एक तरीका है कि प्रत्येक विधि के बंद तरीकों (मेरी पिछली पोस्ट की तरह स्थिर के बजाय) का हिस्सा बनाकर भी आसान है। अब मैं वास्तव में इसे पसंद करता हूं क्योंकि किसी अन्य वर्ग या विधि से 'rwlMyLock_m' पास करने की कोई आवश्यकता नहीं है।

class StackOTest
{
    private delegate DateTime ReadLockMethod();
    private delegate void WriteLockMethod();

    static ReaderWriterLock rwlMyLock_m  = new ReaderWriterLock();
    private DateTime dtMyDateTime_m;
    public DateTime MyDateTime
    {
        get
        {
            return ReadLockedMethod(
                delegate () { return dtMyDateTime_m; }
            );
        }
        set
        {
            WriteLockedMethod(
                delegate () { dtMyDateTime_m = value; }
            );
        }
    }

    private DateTime ReadLockedMethod(ReadLockMethod method)
    {
        rwlMyLock_m.AcquireReaderLock(0);
        try
        {
            return method();
        }
        finally
        {
            rwlMyLock_m.ReleaseReaderLock();
        }
    }

    private void WriteLockedMethod(WriteLockMethod method)
    {
        rwlMyLock_m.AcquireWriterLock(0);
        try
        {
            method();
        }
        finally
        {
            rwlMyLock_m.ReleaseWriterLock();
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.