2010-06-24 7 views
14

यहां मेरा काल्पनिक उदाहरण है। मेरे पास एक बटन के साथ एक बहुत ही सरल WPF विंडो है। बटन। क्लिक घटना में एक हैंडलर है जो इस तरह जाता है।डब्ल्यूपीएफ डिस्पैचर द्वारा अपवादों का प्रचार क्यों नहीं किया जाता है। इन्वोक?

Action doit =() => 
{ 
    Action error =() => { throw new InvalidOperationException("test"); }; 

    try { 
     this.Dispatcher.Invoke(error, DispatcherPriority.Normal); 
    } catch (Exception ex) { 
     System.Diagnostics.Trace.WriteLine(ex); 
     throw; 
    } 
}; 
doit.BeginInvoke(null, null); 

मैं उम्मीद होती है कि अपवाद पकड़ लिया और Trace.WriteLine कॉल से नीचे लिखा जाएगा। इसके बजाए, कोई अपवाद नहीं पकड़ा जाता है और एप्लिकेशन टूट जाता है।

क्या कोई ऐसा होने के लिए संभावित स्पष्टीकरण के बारे में जानता है? और Dispatcher.Invoke द्वारा प्रस्तावित प्रतिनिधि द्वारा दिए गए अपवादों को पकड़ने के लिए आप क्या कामकाज सुझाते हैं?

अद्यतन 1: मैंने अपवाद हैंडलिंग कोड में throw डाला। मैं वास्तव में अपवाद को अनदेखा नहीं करना चाहता हूं। मेरे प्रश्न का पूरा बिंदु इसे सही तरीके से संभालना है। समस्या यह है कि अपवाद हैंडलिंग कोड कभी निष्पादित नहीं होता है।

याद रखें कि यह एक काल्पनिक उदाहरण है। मेरा असली कोड ऐसा नहीं दिखता है। साथ ही, मान लें कि मैं कोड को लागू करने के तरीके में कोड नहीं बदल सकता।

अद्यतन 2: इस समान उदाहरण पर विचार करें। एक WPF विंडो के बजाय, मेरे पास एक विंडोज़ फॉर्म विंडो है। इसमें लगभग एक ही हैंडलर के साथ एक बटन है। आमंत्रण कोड में केवल अंतर ही है। यह इस प्रकार चलता है।

this.Invoke(error); 

विंडोज फॉर्म में, अपवाद हैंडलिंग कोड निष्पादित किया जाता है। अंतर क्यों?

उत्तर

5

UPDATED: अन्य सूत्र में अपवाद का पालन करने के लिए, आप इस तरह के रूप में एक Task उपयोग करने के लिए, Dispatcher धागा करने के लिए इसे क़तार (TaskScheduler.FromCurrentSynchronizationContext का प्रयोग करके), और उस पर प्रतीक्षा करें, हैं:

var ui = TaskScheduler.FromCurrentSynchronizationContext(); 
Action doit =() => 
{ 
    var error = Task.Factory.StartNew(
     () => { throw new InvalidOperationException("test"); }, 
     CancellationToken.None, 
     TaskCreationOptions.None, 
     ui); 

    try { 
     error.Wait(); 
    } catch (Exception ex) { 
     System.Diagnostics.Trace.WriteLine(ex); 
    } 
}; 
doit.BeginInvoke(null, null); 

UPDATED (फिर से): के बाद से अपने लक्ष्य को एक पुन: प्रयोज्य घटक है, मैं एक Task आधारित इंटरफेस या कुछ और SynchronizationContext जैसे event-based asynchronous pattern के आधार पर करने के लिए आगे बढ़, बजाय Dispatcher यापर घटक आधारित की सिफारिश करते हैं।

Dispatcher-आधारित घटक केवल WPF/Silverlight पर काम करते हैं; ISynchronizeInvoke-आधारित घटक केवल विंडोज फॉर्म पर काम करते हैं। SynchronizationContext-आधारित घटक WPF या Windows Forms के साथ पारदर्शी रूप से काम करेंगे, और (कुछ और काम के साथ) ASP.NET, कंसोल ऐप्स, विंडोज सेवाएं इत्यादि

ईवेंट-आधारित एसिंक्रोनस पैटर्न लेखन का पुराना अनुशंसित तरीका है SynchronizationContext-आधारित घटक; यह अभी भी .NET 3.5-युग कोड के लिए है। यदि आप .NET 4 पर हैं, हालांकि, कार्य समानांतर लाइब्रेरी अधिक लचीली, साफ और शक्तिशाली है। TaskScheduler.FromCurrentSynchronizationContext नीचे SynchronizationContext का उपयोग करता है, और इस तरह के सिंक्रनाइज़ेशन की आवश्यकता वाले पुन: प्रयोज्य घटकों को लिखने का नया तरीका है।

+0

जिस तरह से मैं पकड़े गए अपवादों से निपट रहा हूं वह अप्रासंगिक है। मैं कुछ लॉगिंग या जो कुछ भी डाल सकता था। समस्या यह है कि अपवाद हैंडलिंग कोड कभी निष्पादित नहीं होता है। – jpbochi

+0

ऐसा इसलिए है क्योंकि अपवाद को किसी अन्य थ्रेड पर फेंक दिया जाता है - 'डिस्पैचर' थ्रेड। –

+1

@ स्टीफन: मुझे यह पता है। मैं एक लक्ष्यInvocationException या इस तरह कुछ पाने की उम्मीद कर रहा था। – jpbochi

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