2012-01-10 19 views
16

क्यों किसी कार्य के भीतर फेंक दिया अपवाद चुप अपवाद नहीं हैं और आप जानते हैं कि एक निश्चित अपवादटास्क और अपवाद चुप्पी

try 
{ 

Task task = new Task(
() => { 
      throw null; 
     } 
     ); 
    task.Start(); 
} 
catch 
{ 
    Console.WriteLine("Exception"); 
} 

एक पूर्ण मौन में कार्यक्रम चलाने के सफलतापूर्वक निकाल दिया गया है कभी नहीं! जहां धागे का व्यवहार भिन्न

try 
{ 

Thread thread = new Thread(
() => { 
      throw null; 
     } 
     ); 
    thread .Start(); 
} 
catch 
{ 
    Console.WriteLine("Exception"); 
} 

एक अशक्त सूचक अपवाद नहीं है इस मामले में फेंक दिया जाएगा। क्या अंतर है?

उत्तर

15

उस परिदृश्य का व्यवहार आपके ढांचे पर निर्भर करता है; 4.0 में, आपको वास्तव में सावधान रहने की आवश्यकता है - यदि आप TaskScheduler.UnobservedTaskException को संभाल नहीं पाते हैं, तो यह बाद में त्रुटि/समापन होने पर त्रुटि होगी, और आपकी प्रक्रिया को मार देगा।

TaskScheduler.UnobservedTaskException += (sender, args) => 
{ 
    Trace.WriteLine(args.Exception.Message); // somebody forgot to check! 
    args.SetObserved(); 
}; 

4.5, आईआईआरसी में यह परिवर्तन।

एक एक निरंतरता हो सकता है असफल, आप रजिस्टर कर सकता है Task कि के परिणाम की जांच करने के लिए - अर्थात ContinueWith फोन और परिणाम के अपवाद की जाँच करें। वैकल्पिक रूप से, कार्य के .Result तक पहुंच (जो एक अंतर्निहित Wait() भी करेगा) अपवाद को फिर से सतह पर फिर से सतह पर रखेगा। किसी कार्य के परिणाम का निरीक्षण करना अच्छा होता है, क्योंकि यह अंतिमकरण ध्वज को साफ़ करता है, जिसका अर्थ है कि इसे अधिक सस्ता रूप से एकत्र किया जा सकता है।

+0

संस्करण संख्या को 5.0 से 4.5 तक बदल दिया - आशा है कि आपको कोई फर्क नहीं पड़ता। (यह सी # 5 होगा, लेकिन .NET 4.5।) –

+0

@ जोन बिल्कुल नहीं; वास्तव में, मुझे सही करने के लिए धन्यवाद। –

5

नहीं, कार्य धागे नहीं हैं। कार्य एक उच्च स्तरीय अमूर्तता का प्रतिनिधित्व करते हैं - वे काम की एक इकाई हैं जो स्वाभाविक रूप से समानांतर है। थ्रेड काम की इकाइयों को चलाते हैं।

अपने पहले उदाहरण में, आप काम की एक इकाई बनाते हैं और फिर इसे चलाने के लिए कहते हैं (यह कार्य का कार्यान्वयन विवरण कैसे करता है)। जबकि आपके दूसरे उदाहरण में आप स्पष्ट रूप से कार्य की एक इकाई निर्धारित करते हैं (यह कार्य के कार्यान्वयन के लिए एक अलग तरीके से दिखाई देगा)।

+0

ठीक है, लेकिन अपवाद हैंडलिंग के बारे में क्या? –

+0

ओपी अधिक रुचि रखते हैं कि 'टास्क' क्यों नहीं फेंकेंगे जबकि 'थ्रेड' होगा। – Oded

+2

@ स्लेमिंजनेडी कार्य कार्य के पूछताछ के लिए अपवाद संग्रहीत करेंगे। एक धागे में कोई अंतर्निहित अपवाद हैंडलिंग नहीं है, अपवाद पकड़े जाने तक यह ढेर का प्रचार करेगा। –

1

मुझे लगता है कि आपको Task के मामले में अपवाद नहीं मिल रहा है क्योंकि आप मुख्य धागे में अपवाद की प्रतीक्षा नहीं कर रहे हैं। आप अभी जारी हैं task.Wait() रखो और आपको मुख्य धागे में अपवाद मिलेगा।

+1

बहुत सच है, लेकिन निष्पक्ष होना, ज्यादातर मामलों में यह * अपेक्षित * है कि हम तुरंत 'प्रतीक्षा' को कॉल नहीं करेंगे। –

4

निम्नलिखित मानते हैं .NET 4.0, और डिफ़ॉल्ट कार्यस्कूलर का उपयोग करना।

सभी नोटिस पहले कि अपवाद अंदर प्रतिनिधियों आप पारित उठाया जाता है, तो वे, एक अलग धागे में उठाए गए हैं वह नहीं जिसका आप (तार्किक) अपने catch कर रहे हैं में। तो किसी भी तरह अपवाद को थ्रेड से प्रचारित किया जाना चाहिए जो आपके प्रतिनिधि/लैम्ब्डा कोड को थ्रेड/कार्य शुरू करने वाले व्यक्ति को निष्पादित करता है।

नोट Task के लिए, मुझे लगता है कि पुस्तकालय भी अपने आप धागे पर इसे चलाने के लिए नहीं चुन सकते हैं कि, बल्कि बुला धागे पर (लेकिन मुझे यकीन है कि अगर यह है कि केवल Parallel.ForEach, आदि के लिए सच था और नहीं कर रहा हूँ एक "नग्न" Task ऑब्जेक्ट के लिए नहीं)।

के लिए है कि दो होता है, दो बातें पूरा किया जाना चाहिए:

  1. बुला धागा अभी भी सक्रिय है। अन्यथा कुछ भी नहीं बचा है जो वास्तव में पकड़ कर सकता है।
  2. थ्रेड/कार्य में होने वाले अपवाद को किसी भी तरह से संरक्षित किया जाना चाहिए और इसे पकड़ने के लिए आपके लिए पुन: उपयोग किया जाना चाहिए।

ऐसा कहकर, आपके दोनों उदाहरण थ्रेड/कार्य को समाप्त करने की प्रतीक्षा नहीं करते हैं। पहले उदाहरण में आप task.Wait() (या समान) और दूसरे में thread.Join() खो रहे हैं। आपके परीक्षण कोड समय व्यवहार के आधार पर इसका अर्थ यह हो सकता है कि आप थ्रेड/कार्य (ऊपर आइटम 1) से अपवाद का पालन नहीं कर पाएंगे।

  • टास्क उदाहरण:

    यहां तक ​​कि अगर आप दो कॉल जोड़ें यह है कि क्या मुझे (फिर .NET 4.0) के लिए होता है task.Wait() करने के लिए कॉल वास्तव में अपवाद मूल रूप से कार्य में बिना क्रिया छोड़ दिया reraises प्रतिनिधि (यह आपके लिए आंतरिक रूप से टीपीएल करेगा), यह System.AggregateException के अंदर लपेटता है, जिसे आप देख सकते हैं कि क्या आप कुछ और सटीक "कैच-ऑल" के बाद कुछ और सटीक उपयोग करेंगे।

  • थ्रेड उदाहरण: अपवाद प्रतिनिधि द्वारा उठाए बिना क्रिया रहता है और आपके आवेदन बाहर निकलता है इस प्रकार मैं उदाहरण के लिए होता है

दूसरे शब्दों में (जब तक आप unhandled exceptions differently से निपटने के लिए कुछ भी कर):

// Thread example 
var thread = new Thread(() => { throw null; }); 
thread.Start(); 
thread.Join(); 
// Should never reach here, depending on timing sometimes not even 
// until the Join() call. The process terminates as soon as the other 
// thread runs the "throw null" code - which can logically happen somewhere 
// after the "start" of the "Start()" call. 

// Task example 
try 
{ 

    var task = new Task(() => { throw null; }); 
    task.Start(); 
    task.Wait(); 
} 
catch (AggregateException ex) 
{ 
    Console.WriteLine("Exception: " + ex); 
} 
संबंधित मुद्दे