2008-10-23 19 views
7

üzerinden geçersiz kılınan bir yöntem çalıştırıldığında farklı davranan Invoke() ve BeginInvoke() yöntemi, bu kodun neden böyle davrandığını söyleyebilir mi? Kod içinde gömülü olan yorumları görün…Bir delege

Burada gerçekten belirgin bir şey eksik mi?

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

Bunu denedim, ya bir sorun olduğunu farkındaydı, ama bu gelen sorunların çok görebilirsiniz değil. Belki birisi açıklayabilir :) – leppie

cevap

5

Henüz bir cevap yok, ama gariplik göstermek için biraz daha net bir program olduğuna inandıkları vardır: Bu, herhangi bir tekrarlanan aramalara içermeyen

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 

(bu daha basit bir üreme olduğunu kabul ederse, orijinal söz konusu kodunu değiştirmek için çekinmeyin ve benim cevap :)

kaldıracağız: Sonuç olsa aynı tuhaflık hala

Dürüst olmak gerekirse, bu bana bir hata gibi görünüyor. Biraz daha fazla kazacağım.

+0

BeginInvoke için oluşturulan iç kod ile bir hata gibi görünüyor. 2. aramanın stacktrace'ine bakıldığında delegede (hala MyParent.X) yöntem bilgisinin 'doğruluğunu' doğrular. – leppie

+0

Başka bir gariplik, neden bir async çağrısı için kullanılıyor? Sadece basit bir iş parçacığı veya iş parçacığı kullanacağını düşündüm. – leppie

+0

Remoting'i nereden görüyorsunuz? –

0

Belki aradığınız cevabı, ancak bu iş gibi görünüyor:

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

veya

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

Ama kendi muhasebe :(

1

While yapmanız gerekecektir Delegate.Invoke delegate yöntemini doğrudan çağırır, Delegate.BeginInvoke dahili olarak ThreadPool.QueueUserWorkItem() kullanır. Md.Invoke() bir temel sınıfın yöntemleri wi erişilebilir çünkü yalnızca base.X çağrısı başardı. türetilmiş sınıfı temel anahtar kelimeyle incelersiniz. İş parçacığı havuzu tarafından başlatılan temsilci sınıfınıza harici olduğundan, X yöntemine yapılan başvuru, aşağıdaki kod gibi aşırı yüklenmeye tabi tutulur. .NET Framework koduna



    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; 
     } 
    } 

ayıklama: http://blogs.msdn.com/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-framework-source-code.aspx

İlgili konular