2008-10-23 18 views
7

के माध्यम से ओवरराइड करने योग्य विधि को निष्पादित करते समय अलग-अलग व्यवहार करना() और BeginInvoke() आमंत्रित करें क्या कोई मुझे बता सकता है कि यह कोड किस तरह से व्यवहार करता है? कोड में एम्बेडेड टिप्पणियां देखें ...एक प्रतिनिधि

क्या मुझे यहां वास्तव में कुछ याद आ रहा है?

using System; 
namespace ConsoleApplication3 
{ 
    public class Program 
    { 
     static void Main(string[] args) 
     { 
      var c = new MyChild(); 
      c.X(); 
      Console.ReadLine(); 
     } 
    } 

    public class MyParent 
    { 
     public virtual void X() 
     { 
      Console.WriteLine("Executing MyParent"); 
     } 
    } 

    delegate void MyDelegate(); 

    public class MyChild : MyParent 
    { 
     public override void X() 
     { 
      Console.WriteLine("Executing MyChild"); 
      MyDelegate md = base.X; 

      // The following two calls look like they should behave the same, 
      // but they behave differently!  

      // Why does Invoke() call the base class as expected here... 
      md.Invoke(); 

      // ... and yet BeginInvoke() performs a recursive call within 
      // this child class and not call the base class? 
      md.BeginInvoke(CallBack, null); 
     } 

     public void CallBack(IAsyncResult iAsyncResult) 
     { 
      return; 
     } 
    } 
} 
+0

मैं इस की कोशिश की है नहीं, उसे यह जानकारी एक समस्या थी था, लेकिन मैं इस से आ रही मुद्दों का एक बहुत कुछ देख सकते हैं। शायद कोई समझा सकता है :) – leppie

उत्तर

5

मैं अभी तक एक जवाब नहीं है, लेकिन मुझे लगता है मैं विषमता प्रदर्शित करने के लिए एक से थोड़ा स्पष्ट कार्यक्रम होने के लिए विश्वास है:

using System; 

delegate void MyDelegate(); 

public class Program 
{ 
    static void Main(string[] args) 
    { 
     var c = new MyChild(); 
     c.DisplayOddity(); 
     Console.ReadLine(); 
    } 
} 

public class MyParent 
{ 
    public virtual void X() 
    { 
     Console.WriteLine("Executing MyParent.X"); 
    } 
} 

public class MyChild : MyParent 
{ 
    public void DisplayOddity() 
    { 
     MyDelegate md = base.X; 

     Console.WriteLine("Calling Invoke()"); 
     md.Invoke();    // Executes base method... fair enough 

     Console.WriteLine("Calling BeginInvoke()"); 
     md.BeginInvoke(null, null); // Executes overridden method! 
    } 

    public override void X() 
    { 
     Console.WriteLine("Executing MyChild.X"); 
    } 
} 

यह किसी भी पुनरावर्ती कॉल शामिल नहीं है।

Calling Invoke() 
Executing MyParent.X 
Calling BeginInvoke() 
Executing MyChild.X 

(अगर आप सहमत हैं कि यह एक सरल रेप्रो है, मूल प्रश्न में कोड को बदलने के लिए स्वतंत्र लग रहा है और मैं अपने जवाब :)

से निकाल दिया है: परिणाम अभी भी वही विषमता हालांकि है

ईमानदार होने के लिए, यह मेरे लिए एक बग जैसा दिखता है। मैं थोड़ा और खोदना होगा।

+0

यह BeginInvoke के लिए उत्पन्न आंतरिक कोड के साथ एक बग जैसा दिखता है। दूसरे कॉल के स्टैकट्रैक को देखते हुए, प्रतिनिधि (अभी भी MyParent.X) में विधि की जानकारी की 'शुद्धता' की पुष्टि करता है। – leppie

+0

एक और विषमता है, एक एसिंक कॉल के लिए रीमोटिंग का उपयोग क्यों किया जा रहा है? मैंने वास्तव में सोचा कि यह सिर्फ एक साधारण थ्रेड या थ्रेडपूल का उपयोग करेगा। – leppie

+0

आप रिमोटिंग कहां देखते हैं? –

0

हो सकता है कि इस सवाल का जवाब नहीं आप देख रहे हैं, लेकिन यह काम करने के लिए लगता है:

ThreadPool.QueueUserWorkItem(x => md()); 

या

new Thread(() => md()).Start(); 

लेकिन आप अपने खुद के लेखांकन :(

1

जबकि करने की आवश्यकता होगी Delegate.Invoke प्रतिनिधि विधि को सीधे कॉल करता है, Delegate.BeginInvoke आंतरिक रूप से ThreadPool.QueueUserWorkItem() का उपयोग करता है। Md.Invoke() केवल base.X को कॉल करने में सक्षम था क्योंकि बेस क्लास के तरीके सुलभ होते हैं wi बेस कीवर्ड के माध्यम से व्युत्पन्न कक्षा पतली। चूंकि थ्रेड पूल द्वारा शुरू किया गया प्रतिनिधि आपकी कक्षा के बाहर है, इसलिए इसकी एक्स विधि का संदर्भ ओवरलोडिंग के अधीन है, बस नीचे दिए गए कोड की तरह। .NET फ्रेमवर्क कोड में



    public class Program 
    { 
     static void Main(string[] args) 
     { 
      MyChild a = new MyChild(); 
      MyDelegate ma = new MyDelegate(a.X); 

      MyParent b = new MyChild(); 
      MyDelegate mb = new MyDelegate(b.X); 

      ma.Invoke(); 
      mb.Invoke(); 
      ma.BeginInvoke(CallBack, null); 
      mb.BeginInvoke(CallBack, null); //all four calls call derived MyChild.X 

      Console.ReadLine(); 
     } 

     public static void CallBack(IAsyncResult iAsyncResult) 
     { 
      return; 
     } 
    } 

डीबग: http://blogs.msdn.com/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-framework-source-code.aspx

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