2010-04-12 16 views
7

मैं बहुत सारे विंडोज जीयूआई प्रोग्रामिंग नहीं करता हूं, इसलिए यह सभी लोगों के लिए WinForms से अधिक परिचित लोगों के लिए सामान्य ज्ञान हो सकता है। दुर्भाग्य से मैं इस मुद्दे को समझाने के लिए कोई संसाधन नहीं ढूंढ पा रहा हूं, आज मुझे डीबगिंग के दौरान सामना करना पड़ा।Control.EndInvoke अपवाद के लिए कॉल स्टैक रीसेट करता है

अगर हम एंडिनोक को एसिंक प्रतिनिधि पर कॉल करते हैं। विधि को फिर से फेंकने के दौरान हमें कोई अपवाद फेंक दिया जाएगा। कॉल स्टैक अपवाद के मूल स्रोत को प्रतिबिंबित करेगा।

हालांकि, अगर हम Windows.Forms.Control पर कुछ ऐसा करते हैं, तो Control.EndInvoke का कार्यान्वयन कॉल स्टैक को रीसेट करता है। यह एक साधारण परीक्षण या परावर्तक में कोड को देखकर देखा जा सकता है। EndInvoke से प्रासंगिक कोड अंश यहाँ है:

if (entry.exception != null) 
{ 
    throw entry.exception; 
} 

मैं समझता हूँ कि शुरू/EndInvoke नियंत्रण और async प्रतिनिधियों पर अलग हैं, लेकिन मैं Control.EndInvoke पर समान व्यवहार की उम्मीद है।

क्या कोई कारण है नियंत्रण नियंत्रण नहीं करता है जो एसिंक प्रतिनिधि मूल कॉल स्टैक को संरक्षित करने के लिए करते हैं?

उत्तर

1

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

1

ध्यान दें कि Control.EndInvoke फ्रेमवर्क में कुछ प्रबंधित EndInvokes में से एक है (ताकि आप प्रतिबिंब में कोड देख सकें)। उन्हें शायद एक गैर-प्रबंधित सहायक होना चाहिए जो मूल ढेर के साथ जगह पर फेंकता हो।

वास्तव में, मुझे लगता है कि यह केवलEndInvoke कामयाब है, लेकिन वहाँ एक IAsyncResult पैरामीटर के साथ अन्य कामयाब End* दिनचर्या है। मैंने उन सभी की जांच नहीं की है, लेकिन ऐसा लगता है कि मैंने उन सभी की समीक्षा की है जिन्हें मैंने अपवाद फेंक दिया है, या प्रभावी रूप से स्टीफन क्लेरी के उपयोग का उपयोग करने के लिए प्रभावी रूप से उपयोग करने के लिए .NET 4 के GetWaiter.GetResult का उपयोग किया है, जिसमें कुछ प्रबंधित और अप्रबंधित शेंगेनियां प्राप्त करने का प्रयास करने के लिए हैं अपवाद के लिए बहाल स्टैक।

1

मैं क्यों नियंत्रण इस (शायद सिर्फ एक निरीक्षण) नहीं करता है यकीन नहीं है, लेकिन आप इसे चारों ओर में .NET 4.0 यूआई फार्म के लिए एक टास्क से निर्धारित कर काम कर सकते हैं:

private BackgroundWorker bgw; 
    private TaskFactory uiTaskFactory; 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     this.uiTaskFactory = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext()); 
     this.bgw = new BackgroundWorker(); 
     this.bgw.DoWork += bgw_DoWork; 
     this.bgw.RunWorkerAsync(); 
    } 

    void bgw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     var task = this.uiTaskFactory.StartNew(this.OuterTaskFunction); 
     try 
     { 
      task.Wait(); 
     } 
     catch (Exception ex) 
     { 
      // Note: Full stack trace preserved 
      MessageBox.Show(ex.InnerException.ToString()); 
     } 
    } 

    void OuterTaskFunction() 
    { 
     this.InnerTaskFunction(); 
    } 

    void InnerTaskFunction() 
    { 
     throw new InvalidOperationException("Blah."); 
    } 
-3

मैं आपके संदेश का 100% नहीं पढ़ा है, इसलिए मुझे यकीन नहीं है कि यह मदद करता है या मैं केवल स्पष्ट चीजें कह रहा हूं, लेकिन जब कोई अपवाद पकड़ा जाता है और आप

"फेंक iAmAnCaughtExceptionInstance;"

कॉल स्टैक को सहेजा नहीं जाएगा, तो आप सिर्फ लिखना चाहिए

"फेंक,"

और फिर कॉल स्टैक सहेजा जाता है

+1

मुझे पता है, लेकिन जब से मैं एक है जो लागू नहीं किया हूँ Windows.Forms.Control यह थोड़ी मदद की है। –

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