C# 多線程系列之異步回調(委托)


本文參考自C#基礎:線程之異步回調(委托),純屬讀書筆記

在解析異步回調之前,先看同步回調的執行過程,以及代碼原理。

1、線程的同步執行

同步執行:在主線程執行的時候,主線程調用一個其它方法,此時主線程阻塞,等待調用方法執行完成后主線程才能繼續執行。

代碼如下:

    class Program
    {
        static void Main(string[] args)
        {
            for (int i = 1; i < 11; i++) {
                if (i == 5) {
                    Console.WriteLine("調用TakeAWhile方法並等待其執行完成");
                    Console.WriteLine("開始執行TakeAWhile方法,時間:{0}", DateTime.Now);
                    int result = TakeAWhile(0, 6000);
                    if (result == 1) {
                        Console.WriteLine("TakeAWhile方法執行完成");
                    }
                    Console.WriteLine("TakeAWhile方法執行完畢,時間:{0}", DateTime.Now);
                }
                Thread.Sleep(30);
                Console.WriteLine(i.ToString());
            }
        }
        static int TakeAWhile(int data, int time) {
            Thread.Sleep(time);
            return ++data;
        }
    }

 

從上面的結果得出當程序開始調用TakeAWhile方法后,主線程阻塞,當TakeAWhile方法調用完畢之后,主線程又重新開始運行,這個過程就是線程的同步執行的過程.

 

2、線程的異步執行

what is 異步執行?

異步執行:在主線程執行的時候,打開一個子線程,主線程不會像同步執行的那樣等待子線程的結果返回后在執行,主線程會繼續執行,當主線程需要子線程的運行結果時,主線程直接調用子線程的運行結果,如果子線程的運行結果還沒有出來,那么主線程等待,直到子線程執行結束,主線程拿到子線程的運行結果,主線程在繼續。

 class Program
    {
        static void Main(string[] args)
        {
            Func<int, int, int> fun = TakeAWhile;
            IAsyncResult ar = fun.BeginInvoke(0, 1000, null, null);//主線程調用子線程開始執行TakeAWhile方法,並給它傳遞了參數
            int times=1;
            while (!ar.IsCompleted)
            {
                //當子線程沒有完成之前,主線程可以在該while語句塊內進行任何后續操作,而且不用等待子線程的結束
                Console.WriteLine(times++);
                Thread.Sleep(50);
            }
            int result = fun.EndInvoke(ar);//1秒之后我需要子線程的結果了,ok,從子線程中拿到結果
            Console.WriteLine("TakeAWhile方法結束,時間是:{0}", DateTime.Now);
            Console.WriteLine("result:{0}", result);
            Console.ReadKey();
        }

        static int TakeAWhile(int data, int times)
        {
            Console.WriteLine("TakeAWhile方法開始執行,時間是:{0}",DateTime.Now);
            Thread.Sleep(times);
            return ++data;
        }
    }

從結果和代碼進行分析,當通過BeginInvoke方法開始異步執行TakeAWhile方法,主線程繼續執行,然后通過IsCompleted屬性判斷TakeAWhile是否執行完成,最后獲取子線程的輸出值,並輸出其結果,整個過程主線程沒有因為在執行子線程的原因,而造成阻塞

 注:因為多線程,導致了這個情況,開啟子線程和執行子線程中的方法都需要時間,所以主線程的執行速度快於子線程,所以先輸出了一個1;解決方法很簡單,讓主線程休息一會,等子線程先初始化完,代碼如下:

class Program
    {
        static void Main(string[] args)
        {
            Func<int, int, int> fun = TakeAWhile;
            IAsyncResult ar = fun.BeginInvoke(0, 1000, null, null);//主線程調用子線程開始執行TakeAWhile方法,並給它傳遞了參數
            Thread.Sleep(30);//休息一會
            int times=1;
            while (!ar.IsCompleted)
            {
                //當子線程沒有完成之前,主線程可以在該while語句塊內進行任何后續操作,而且不用等待子線程的結束
                Console.WriteLine(times++);
                Thread.Sleep(50);
            }
            int result = fun.EndInvoke(ar);//6秒之后我需要子線程的結果了,ok,從子線程中拿到結果
            Console.WriteLine("TakeAWhile方法結束,時間是:{0}", DateTime.Now);
            Console.WriteLine("result:{0}", result);
            Console.ReadKey();
        }

        static int TakeAWhile(int data, int times)
        {
            Console.WriteLine("TakeAWhile方法開始執行,時間是:{0}",DateTime.Now);
            Thread.Sleep(times);
            return ++data;
        }
    }

 

3、異步回調

what is 異步異步回調?

異步回調:主線程在執行的時候,打開一個子線程,主線程繼續執行,當子線程執行完成的時候,主線程立即輸出子線程的運行結果,主線程繼續執行。

class Program
    {
        static void Main(string[] args)
        {
            Func<int, int, int> fun = TakeAWhile;
            fun.BeginInvoke(0, 1000, TakesAWhileCallBack, fun);//異步調用TakeAWhile,並指定回調函數TakesAWhileCallBack
            for (int i = 0; i < 20; i++)
            {
                Console.WriteLine(i.ToString());
                Thread.Sleep(100);
            }
            Console.ReadKey();
        }
        static int TakeAWhile(int data, int times) {
            Console.WriteLine("TakeAWhile方法開始執行,時間是:{0}", DateTime.Now);
            Thread.Sleep(times);
            return ++data;
        }
        /// <summary>
        /// 回調函數
        /// </summary>
        /// <param name="fun">調用的委托</param>
        static void TakesAWhileCallBack(IAsyncResult fun)
        {
            if (fun == null)
                throw new ArgumentNullException("fun");
            Func<int, int, int> dl = (Func<int, int, int>)fun.AsyncState;
            int result = dl.EndInvoke(fun);
            Console.WriteLine("我是回調函數返回的結果:{0}", result);
            Console.WriteLine("TakeAWhile執行完成,時間是:{0}", DateTime.Now);
        }
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM