Invoke () and BeginInvoke () behave differently when executing an overridable method through a delegate

Can someone tell me why this code behaves the way it does? See Comments embedded in code ...

Did I miss something really obvious here?

using System; namespace ConsoleApplication3 { public class Program { static void Main(string[] args) { var c = new MyChild(); cX(); 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; } } } 
+7
override invoke begininvoke virtual delegates
source share
3 answers

I don’t have an answer yet, but I have what I think is a little more understandable for demonstrating weirdness:

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

This does not involve any recursive calls. As a result, the same strangeness remains:

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

(If you agree that this is a simpler option, feel free to replace the code in the original question, and I will remove it from my answer :)

Honestly, this seems like a mistake. I will dig a little more.

+5
source share

While Delegate.Invoke calls the delegate method directly, Delegate.BeginInvoke internally uses ThreadPool.QueueUserWorkItem (). md.Invoke () could only call base.X because the base class methods are available in the derived class via the base keyword. Since the delegate launched by the thread pool is external to your class, the reference to its method X is overloaded, as is the code below.

 public class Program { static void Main(string[] args) { MyChild a = new MyChild(); MyDelegate ma = new MyDelegate(aX); MyParent b = new MyChild(); MyDelegate mb = new MyDelegate(bX); 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; } } 

Debugging in the .NET Framework: http://blogs.msdn.com/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-framework-source-code.aspx

+1
source share

Maybe not the answer you are looking for, but this works:

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

or

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

But you will need to make your own accounting :(

0
source share

All Articles