मुझे लगता है कि आशावादी को isCompleteचर पर 'अस्थिर' कीवर्ड की कमी से मूर्ख बनाया गया है ।
बेशक, आप इसे जोड़ नहीं सकते, क्योंकि यह एक स्थानीय चर है। और निश्चित रूप से, चूंकि यह एक स्थानीय चर है, इसलिए इसकी बिल्कुल भी आवश्यकता नहीं होनी चाहिए, क्योंकि स्थानीय लोगों को स्टैक पर रखा जाता है और वे स्वाभाविक रूप से हमेशा "ताजा" होते हैं।
हालांकि , संकलन के बाद, यह अब एक स्थानीय चर नहीं है । चूंकि यह एक अनाम प्रतिनिधि में एक्सेस किया जाता है, कोड विभाजित होता है, और यह एक सहायक वर्ग और सदस्य क्षेत्र में अनुवादित होता है, कुछ इस प्रकार है:
public static void Main(string[] args)
{
TheHelper hlp = new TheHelper();
var t = new Thread(hlp.Body);
t.Start();
Thread.Sleep(500);
hlp.isComplete = true;
t.Join();
Console.WriteLine("complete!");
}
private class TheHelper
{
public bool isComplete = false;
public void Body()
{
int i = 0;
while (!isComplete) i += 0;
}
}
मैं अब कल्पना कर सकता हूं कि प्रसंस्करण TheHelperवर्ग जब एक मल्टीथ्रेडेड वातावरण में जेआईटी कंपाइलर / ऑप्टिमाइज़र , वास्तव में विधि की शुरुआत में कुछ रजिस्टर या स्टैक फ्रेम में मूल्य को कैश कर सकता है , और विधि समाप्त होने तक इसे कभी भी ताज़ा नहीं करता है। ऐसा इसलिए है क्योंकि कोई भी गारंटी नहीं है कि "= सच" निष्पादित होने से पहले धागा और विधि समाप्त नहीं होगी, इसलिए यदि कोई गारंटी नहीं है, तो इसे कैश क्यों न करें और इसे पढ़ने के बजाय एक बार ढेर ऑब्जेक्ट को पढ़ने के प्रदर्शन को बढ़ावा दें। यात्रा।falseBody()
यही कारण है कि कीवर्ड volatileमौजूद है।
इस सहायक स्तरीय होने के लिए सही एक छोटे से थोड़ा बेहतर थोड़ा 1) मल्टी-थ्रेडेड वातावरण में, यह होना चाहिए:
public volatile bool isComplete = false;
लेकिन, ज़ाहिर है, चूंकि यह ऑटोगेन्जेनेटेड कोड है, इसलिए आप इसे नहीं जोड़ सकते। एक बेहतर तरीका यह है कि कुछ lock()एस को पढ़ने और लिखने के लिए जोड़ा जाए isCompletedया कुछ अन्य रेडी-टू-यूज़ सिंक्रनाइजेशन या थ्रेडिंग / टास्किंग उपयोगिताओं का उपयोग करने के बजाय इसे नंगे-धातु करने की कोशिश की जाए (जो कि यह नंगे-धातु नहीं होगा , चूंकि यह जीसी, जेआईटी और (..) के साथ सीएलआर पर सी # है।
डिबग मोड में अंतर शायद इसलिए होता है क्योंकि डिबग मोड में कई ऑप्टिमाइज़ेशन को बाहर रखा जाता है, इसलिए आप स्क्रीन पर देखे गए कोड को अच्छी तरह से डिबग कर सकते हैं। इसलिए while (!isComplete)अनुकूलित नहीं है, इसलिए आप वहां एक ब्रेकपॉइंट सेट कर सकते हैं, और इसलिए isCompleteआक्रामक तरीके से रजिस्टर या स्टैक में कैश नहीं किया जाता है और हर लूप पुनरावृत्ति पर हीप से ऑब्जेक्ट से पढ़ा जाता है।
Btw। उस पर बस मेरा अनुमान है। मैंने इसे संकलित करने की कोशिश भी नहीं की।
Btw। यह एक बग नहीं लगता है; यह बहुत अस्पष्ट साइड इफेक्ट की तरह है। इसके अलावा, अगर मैं इसके बारे में सही हूं, तो यह एक भाषा की कमी हो सकती है - सी # को स्थानीय चर पर 'अस्थिर' कीवर्ड को रखने की अनुमति देनी चाहिए जो बंद क्षेत्रों में सदस्य क्षेत्रों पर कब्जा कर लिया गया है और पदोन्नत किया गया है।
1) के बारे में एरिक Lippert से एक टिप्पणी के लिए नीचे देखें volatileऔर / या इस बहुत ही दिलचस्प है कि कोड पर निर्भर सुनिश्चित करने में शामिल जटिलता के स्तर दिखा लेख volatileहै सुरक्षित ..uh, अच्छा ..uh, चलो ठीक कहते हैं करते हैं।