委派的非同步呼叫 Delegates BeginInvoke()、EndInvoke()

非同步呼叫BeginInvoke()、EndInvoke()

這邊用了3個類別ClassWithDelegate(提供事件讓外部註冊)、FirstSubClass、SecondSubClass(註冊ClassWithDelegate事件)
在執行過程中,發現必須等到FirstSubClass的方法處理完成後,SecondSubClass方法才會執行。
這是因為委派類別的方法Invoke()必須等待事件處理完成後,才能繼續。
所以必須改用BeginInvoke(AsyncCallback callBack, object 呼叫所需方法的委派)、EndInvoke(IAsyncResult ar)
        class ClassWithDelegate
        {
            public delegate int RegisterDelegate(); //定義委派
            public event RegisterDelegate MyDel;  //將委派作為事件,提供外部註冊
 
            public void Run()
            {
                for (; ; )
                {
                    if (MyDel!=null) //是否有事件註冊
                    {
                        Thread.Sleep(500);
                        foreach (RegisterDelegate del in MyDel.GetInvocationList())
                        {
                            Console.WriteLine("{0}, {1:d}", del.Target, del.Invoke()); //del.Target 取得目前委派用來叫用'執行個體方法'的類別執行個體。
                        }
                    }
                }
            }
        }
 
        class FirstSubClass
        {
            public FirstSubClass(ClassWithDelegate supperClass)
            {
                supperClass.MyDel += new ClassWithDelegate.RegisterDelegate(supperClass_MyDel); //進行事件註冊
            }
 
            int supperClass_MyDel()
            {
                Thread.Sleep(10000); //停止10秒,模擬在這個事件需要處理大量的資料
 
                return (new Random().Next(1, 100)); //回傳1~100亂數
            }
        }
 
        class SecondSubClass
        {
            public SecondSubClass(ClassWithDelegate supperClass)
            {
                supperClass.MyDel += new ClassWithDelegate.RegisterDelegate(supperClass_MyDel); //進行事件註冊
            }
 
            int supperClass_MyDel()
            {
                return (new Random().Next(101,150)); //回傳101~150亂數
            }
        }
        
        static void Main(string[] args)
        {
            ClassWithDelegate superClass = new ClassWithDelegate();
 
            FirstSubClass firstClass = new FirstSubClass(superClass);
            SecondSubClass secondClass = new SecondSubClass(superClass);
           //當執行方法Run()時,因為FristSubClass、SecondSubClass內部的方法,已經對superClass的委派RegisterDelegate()進行註冊
           //所以會執行FristSubClass、SecondSubClass內部的方法,並回傳結果。
            superClass.Run();
        }


※改用BeginInvoke()、EndInvoke(),BeginInvoke會自行另外建立執行緒,並等待直到完成。
執行後會發現,SecondSubClass不等待FirstSubClass執行完成,而是立即返回結果。
        class ClassWithDelegate
        {
            public delegate int MyDelegate();
            public event MyDelegate myDel;
 
            public void Run()
            {
                for (; ; )
                {
                    if (myDel != null)
                    {
                        Thread.Sleep(500);
                        foreach (MyDelegate del in myDel.GetInvocationList())
                        {
                            del.BeginInvoke(new AsyncCallback(EndInvoke), del);
                        }
                    }
                }
 
            }
 
            private void EndInvoke(IAsyncResult iar)
            {
                MyDelegate myDel = (MyDelegate)iar.AsyncState;  
                //委派以object隱藏在IAsyncResult的AsyncState屬性中,將它轉為原類型
                int result = myDel.EndInvoke(iar);
 
                Console.WriteLine("{0}, {1:d}", myDel.Target, result);
            }
        }
 
        class FirstSubClass
        {
            public FirstSubClass(ClassWithDelegate superClass)
            {
                superClass.myDel+=new ClassWithDelegate.MyDelegate(CallBack);
            }
 
            private int CallBack()
            {
                Thread.Sleep(10000);
                return (new Random().Next(1, 100));
            }
        }
 
        class SecondSubClass
        {
            public SecondSubClass(ClassWithDelegate superClass)
            {
                superClass.myDel += new ClassWithDelegate.MyDelegate(CalBack);
            }
 
            private int CalBack()
            {
                return (new Random().Next(101, 150));
            }
        }
 
        static void Main(string[] args)
        {
            ClassWithDelegate superClass = new ClassWithDelegate();
            FirstSubClass firstClass = new FirstSubClass(superClass);
            SecondSubClass secondClass = new SecondSubClass(superClass);
            superClass.Run();
        }