2012-05-25 16 views
19

जब मैं डीबग मोड में निम्न कोड चलाता हूं, तो यह सफलतापूर्वक समाप्त हो जाएगा और बाहर निकल जाएगा। हालांकि, अगर मैं निम्नलिखित कोड को मोड में चलाता हूं, तो यह एक अनंत लूप में फंस जाएगा और कभी खत्म नहीं होगा।रिलीज मोड में अनंत लूप

static void Main(string[] args) 
{ 
    bool stop = false; 

    new Thread(() => 
    { 
     Thread.Sleep(1000); 
     stop = true; 
     Console.WriteLine("Set \"stop\" to true."); 

    }).Start(); 

    Console.WriteLine("Entering loop."); 

    while (!stop) 
    { 
    } 

    Console.WriteLine("Done."); 
} 

कौन सा अनुकूलन इसे अनंत लूप में फंसने का कारण बन रहा है?

+0

क्या थ्रेड के बीच 'स्टॉप' तक पहुंच को सिंक्रनाइज़ करने की आवश्यकता नहीं है? –

+0

कुछ अनुकूलन सामग्री के कारण यह है। संकलन स्टॉप का एक सच्चा इंस्टाट तैयार करेगा। – rekire

+0

नई रद्दीकरण टोकन कक्षाओं पर नज़र डालें। इस मुद्दे को हल करने के लिए उनका आविष्कार किया गया था। http://msdn.microsoft.com/en-us/library/dd997364.aspx –

उत्तर

18

मेरा अनुमान मुख्य धागे पर stop चर के प्रोसेसर कैशिंग होगा। डीबग मोड में मेमोरी मॉडल कठोर है क्योंकि डीबगर को सभी धागे में परिवर्तनीय के राज्य का एक समझदार दृश्य प्रदान करने में सक्षम होना चाहिए।

कोशिश एक क्षेत्र बनाने और volatile के रूप में यह अंकन:

volatile bool stop = false; 

static void Main(string[] args) 
{ 

    new Thread(() => 
    { 
     Thread.Sleep(1000); 
     stop = true; 
     Console.WriteLine("Set \"stop\" to true."); 

    }).Start(); 

    Console.WriteLine("Entering loop."); 

    while (!stop) 
    { 
    } 

    Console.WriteLine("Done."); 
} 
+0

अस्थिरता शुद्धता के लिए अच्छा है, लेकिन ऑप्टिमाइज़ेशन से बचने के लिए यह स्थानीय चर के बजाय इसे फ़ील्ड बनाने जैसा दिखता है। –

+0

@AlexeiLevenkov मुझे गलत हो सकता है लेकिन मेरा मानना ​​है कि सीएलआर का कार्यान्वयन विवरण है, और सैद्धांतिक रूप से (हालांकि संभवतः व्यावहारिक रूप से नहीं) परिवर्तन के अधीन है। –

+0

मुझे आश्चर्य है कि आप चर के उपयोग को सिंक्रनाइज़ क्यों नहीं कर रहे हैं। मैं हमेशा ऐसा करता हूं, क्योंकि मुझे लगता है कि यह 'बूल' वैरिएबल प्राप्त करने/सेट करने के लिए परमाणु संचालन नहीं है। क्या मैं इसके बारे में गलत हूं? –

11

क्योंकि यह थ्रेड सुरक्षित नहीं है, इसलिए आप मुख्य थ्रेड वेरिएबल stop को बच्चे धागे के अंदर अपडेट करते हैं। यह हमेशा अप्रत्याशित होगा। इस तरह की किसी भी स्थिति के साथ काम करने के लिए, this article पर एक नज़र डालें।

अस्थिर कीवर्ड संकलक निर्देश देता है कि हर उस क्षेत्र से पढ़ने पर एक अधिग्रहण-बाड़, और पर एक रिलीज-बाड़ हर उस क्षेत्र के बारे में उत्पन्न करने के लिए। एक अधिग्रहण-बाड़ अन्य बाड़ से पहले स्थानांतरित होने से पढ़ता/लिखता है; एक रिलीज-बाड़ बाड़ के बाद स्थानांतरित होने से अन्य पढ़ने/लिखने से रोकता है। ये "अर्ध-बाड़" पूर्ण बाड़ से तेज हैं क्योंकि वे रनटाइम और ऑप्टिमाइज़ेशन के लिए हार्डवेयर अधिक दायरे देते हैं।

0

थ्रेड असुरक्षित कोड अप्रत्याशित है। मुख्य समस्या एक थ्रेड वैरिएबल को दूसरे थ्रेड से बदल रही है। परिवर्तनीय वैश्विक या अस्थिर बनाओ। आप

static volatile bool stop = false; 

static void Main(string[] args) 
{  
    new Thread(() => 
    { 
     Thread.Sleep(1000); 
     stop = true; 
     Console.WriteLine("Set \"stop\" to true."); 

    }).Start(); 

    Console.WriteLine("Entering loop."); 

    while (!stop) 
    { 
    } 

    Console.WriteLine("Done."); 
} 
0

का पालन करते हुए यह कर सकते हैं स्थानीय चर के मूल्य के लिए अनुकूलन के कुछ प्रकार की तरह लग रहा है - एक क्षेत्र के लिए बदल रहा है (ध्यान दें कि अस्थिर या सही ताला वास्तविक कोड में इस्तेमाल किया जाना चाहिए) यह ठीक समाप्त करें:

using System; 
using System.Threading; 

class Program 
{ 
    static bool stop = false; 
    static void Main(string[] args) 
    { 

     new Thread(() => 
     { 
      Thread.Sleep(1000); 
      stop = true; 
      Console.WriteLine("Set \"stop\" to true."); 

     }).Start(); 

     Console.WriteLine("Entering loop."); 

     while (!stop) 
     { 
     } 

     Console.WriteLine("Done."); 
    } 
} 
संबंधित मुद्दे