2010-05-13 12 views
7

मैं सामान्य सी # विकास की एक पुस्तक के माध्यम से जा रहा हूं, और मैं धागा निरस्त खंड में आया हूं।ThreadAbortException को पकड़ते समय छिपे हुए थ्रो के साथ क्या सौदा है?

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

using System; 
using System.Threading; 

public class EntryPoint 
{ 
    private static void ThreadFunc() 
    { 
     ulong counter = 0; 
     while (true) 
     { 
      try 
      { 
       Console.WriteLine("{0}", counter++); 
      } 
      catch (ThreadAbortException) 
      { 
       // Attempt to swallow the exception and continue. 
       Console.WriteLine("Abort!"); 
      } 
     } 
    } 

    static void Main() 
    { 
     try 
     { 
      Thread newThread = new Thread(new ThreadStart(EntryPoint.ThreadFunc)); 
      newThread.Start(); 
      Thread.Sleep(2000); 

      // Abort the thread. 
      newThread.Abort(); 

      // Wait for thread to finish. 
      newThread.Join(); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
    } 
} 

पुस्तक का कहना है:

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

तो मैंने थ्रेड के आसपास एक कोशिश पकड़ लिया। एबॉर्ट() कॉल करें और ब्रेक प्वाइंट सेट करें, यह कहने के लिए कि यह कहने के लिए "कोई बाहरी अपवाद हैंडलर या अंत में ब्लॉक सामान्य रूप से निष्पादित होंगे"। लेकिन यह नहीं करता है। मैं अपने दिमाग को क्यों समझ रहा हूं कि क्यों।

किसी के पास कोई विचार नहीं है कि ऐसा क्यों नहीं है? क्या किताब गलत है?

अग्रिम धन्यवाद।

+1

आपका प्रोग्राम आउटपुट क्या करता है? –

+1

मुझे आशा है कि पुस्तक में यह भी उल्लेख किया गया है कि थ्रेड। एबॉर्ट बुरा है और इसका कभी भी उपयोग नहीं किया जाना चाहिए। –

+0

जितना संभव हो उतना # लिखने के लगभग 20 सेकंड, फिर निरस्त करें !, फिर यह लौटता है। – priehl

उत्तर

8

अपवाद को थ्रेड पर फेंक दिया गया है। एक बार अपवाद फेंकने के बाद उस धागे के कॉल स्टैक की यात्रा होती है, लेकिन यह 0 थर्मके कॉलर तक नहीं पहुंचती है।

दावा किया गया था:

इसलिए, किसी भी बाहरी अपवाद संचालकों या अंत में ब्लॉक अभी भी सामान्य रूप निष्पादित करेंगे।

private static void ThreadFunc() 
{ 
    ulong counter = 0; 
    while (true) 
    { 
     try 
     { 
      try 
      { 
       Console.WriteLine("{0}", counter++); 
      } 
      catch (ThreadAbortException) 
      { 
       // Attempt to swallow the exception and continue. 
       Console.WriteLine("Abort!"); 
      } 
     } 
     catch (ThreadAbortException) 
     { 
      Console.WriteLine("Do we get here?"); 
     } 
    } 
} 

तो ThreadAbortException अपवाद हम लाइन "Do we get here?" हिट करने के लिए की अपेक्षा नहीं की एक सामान्य प्रकार थे, लेकिन हम करते हैं:

इस दावे का एक बेहतर परीक्षण निम्नलिखित कोड है।

1

थ्रेड.एबॉर्ट() अपवाद फेंक नहीं देता है। इसके बजाय, धागे में एक अपवाद फेंक दिया जाता है, और यहां तक ​​कि यदि आप इसे पकड़ते हैं, तो तुरंत इसे पुनर्स्थापित कर दिया जाता है। आपके मामले में, इसे "निरस्त करें" प्रिंट करने के बाद इसे ठीक किया जाएगा। आगे बढ़ें और अपने थ्रेड विधि के शरीर को किसी अन्य प्रयास/पकड़ में लपेटें और आप इसकी पुष्टि करने में सक्षम होंगे।

1

आप शायद इसे देखने के लिए अपनी आंखों को बहुत तेज़ कर दें। इस तरह अपने कोड को संशोधित करें:

 // Wait for thread to finish. 
     newThread.Join(); 
     Console.ReadLine(); 

संभावित उत्पादन:

.... 
8807 
8808 
Abort! 
0

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

using System; 
using System.Threading; 

public class EntryPoint 
{ 
    private static void ThreadFunc() 
    { 
     try 
     { 
      ulong counter = 0; 
      while (true) 
      { 
       try 
       { 
        Console.WriteLine("{0}", counter++); 
       } 
       catch (ThreadAbortException) 
       { 
        // Attempt to swallow the exception and continue. 
        Console.WriteLine("Abort!"); 
       } 
      } 
     } 
     catch(ThreadAbortException) 
     { 
      Console.WriteLine("Certainly unstoppable!"); 
     } 
    } 

    static void Main() 
    { 
     try 
     { 
      Thread newThread = new Thread(new ThreadStart(EntryPoint.ThreadFunc)); 
      newThread.Start(); 
      Thread.Sleep(2000); 

      // Abort the thread. 
      newThread.Abort(); 

      // Wait for thread to finish. 
      newThread.Join(); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
    } 
} 

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

+0

मैं मानता हूं कि थ्रेड। एबॉर्ट थ्रेड को बंद करने का एक भयानक तरीका है। ऐसा कहकर, मैंने कभी-कभी इसका इस्तेमाल किया है जब थ्रेड सिग्नल का जवाब देने से इंकार कर देता है और नियंत्रण थ्रेड धैर्य से बाहर हो जाता है। –

1

उस पुस्तक को कहा जाना चाहिए कि आपको कभी भी Thread.Abort का उपयोग नहीं करना चाहिए क्योंकि इसमें बड़ी मात्रा में समस्याएं हैं।

इस प्रकार, आपके द्वारा देखे जाने वाले किसी भी गैर-स्पष्ट या अप्रत्याशित व्यवहार को संकेत के रूप में लिया जाना चाहिए कि आपको वास्तव में Thread.Abort का उपयोग नहीं करना चाहिए।

Thread.Abort का बिंदु एक थ्रेड को सिग्नल करना है कि एप्लिकेशन समाप्त हो रहा है, आप अच्छी तरह से बाहर निकलने में विफल रहे हैं (मैंने पूछा है), और अब आपको मरना होगा। इसके बारे में क्षमा करें, लेकिन यह वही तरीका है।

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

एक सहकारी विधि आमतौर पर ऐसा करने का सबसे अच्छा तरीका है। सिग्नल का उपयोग करें (यहां तक ​​कि एक अस्थिर बूलियन क्षेत्र के रूप में सरल कुछ भी), और जब आप थ्रेड को बाहर निकलना चाहते हैं तो सिग्नल सेट करें। समय-समय पर इस सिग्नल को अन्य धागे में जांचें, और सेट करते समय बाहर निकलें। या ... यदि आप सिग्नल का पता लगाते हैं तो भी एक अपवाद फेंक दें।

बस कभीThread.Abort का उपयोग करके बाहर से अपवाद लगाता है।

अब कहा गया है कि, यदि आप वास्तव में यह अपवाद कैसे संभालना चाहते हैं, तो आप रनटाइम को सिग्नल कर सकते हैं कि आप स्वचालित रूप से स्टैक को प्रसारित करने के अपवाद को नहीं चाहते हैं (ThreadAbortException एक विशेष मामला है) Thread.ResetAbort() पर कॉल करना।

हालांकि, आप ऐसा नहीं करना चाहिए।

संबंधित मुद्दे