.net5 core webapi進階之四:異步編程(下篇)BeginInvoke( )/EndInvoke( )的使用


實現異步操作,除了用 async 和 await 這對組合之外,還可以通過委托對象的 BeginInvoke( ) 和 EndInvoke( ) 來完成 ,

為簡單起見,我們直接使用系統為我們提供的內置委托 Func<T1,T2,...TResult>(或者不帶返回值的Action<T1,T2...>委托也可以) ,代碼如下:

(注:目前.net5 core 還不支持 BeginInvoke() 和 EndInvoke() 這種異步調用形式,需要用 .net5  framework環境 。)

  class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            Console.WriteLine("Main Thread ID = " + Thread.CurrentThread.ManagedThreadId);

            Demo51();

            Console.ReadLine();
        }
         
        private static int Demo51()
        {
            //定義一個Func<int,int>類型的委托 fx,功能:輸入一個整數,+100后輸出。
            Func<int, int> fx = new Func<int, int>(
                x => {
                    Console.WriteLine("Func<int, int>() Thread ID = " + Thread.CurrentThread.ManagedThreadId); 
                    return x + 100; 
                }
            );

            int ret = fx.Invoke(28); // Invoke() 是同步調用,即在當前主線程中調用 fx

            // BeginInvoke() 是異步調用,主線程會在線程池中取一個新線程來執行 fx,主線程會繼續往下執行
            IAsyncResult iar = fx.BeginInvoke(28, null, null);
    
            // do something1....這里可以加入業務代碼

            // EndInvoke() 用於獲取 fx 的執行結果並釋放線程使用的資源,在獲取到結果之前主線程不會繼續往下執行
            int val = fx.EndInvoke(iar);
 
            // do something2....這里可以加入業務代碼

            return val;
        } 
    }

 運行程序其結果如下,可以看到調用 fx.Invoke( ) 和 fx.BeginInvoke( )的運行線程是不一樣的。

 

在上面的例子中,當主線程執行到 "int val = fx.EndInvoke(iar);" 這條語句時如果 fx 還未執行完成,

主線程不會繼續往下執行,會一直等待 fx 的執行結果,這種方式叫 "等待直到完成(wait-until-done)" 模式 ,

除了這種模式外,還有另外2種模式,分別是 "輪詢(polling)"模式 和 "回調(callback)"模式,具體如下:

 

2. 輪詢(polling)模式

     private int Demo52()
        {

       //定義一個Func<int,int>類型的委托 fx,功能:輸入一個整數,+100后輸出。 Func<int, int> fx = new Func<int, int>( x => { Console.WriteLine("Func<int, int>() Thread ID = " + Thread.CurrentThread.ManagedThreadId); return x + 100; } );

// BeginInvoke() 是異步調用,即在線程池中取一個新線程來執行 fx IAsyncResult iar = fx.BeginInvoke(28, null, null); // do something1....這里可以加入業務代碼 // 判斷 IAsyncResult.IsCompleted 屬性來輪詢 fx 是否執行完成 while (iar.IsCompleted == false) { // do something....這里可以加入業務代碼 } // EndInvoke() 用於獲取 fx 的執行結果並釋放線程使用的資源 int val = fx.EndInvoke(iar); // do something2....這里可以加入業務代碼 return val; }

輪詢(polling)模式通過 IAsyncResult.IsCompleted 屬性來判斷 fx 是否執行完成 ,

我們可以在完成前和完成后做一些業務處理(測試略)。

 

3. 回調(callback)模式

        private int callbackResult=0;
        private void CallbackFunc(IAsyncResult iar)
        {
            // state="test param",對應fx.BeginInvoke()的最后一個參數
            string state = (string)iar.AsyncState;

            // 強制轉型用於后面獲取委托對象 fx
            AsyncResult ar = (AsyncResult)iar;
            Func<int, int> fx = (Func<int, int>)ar.AsyncDelegate;

            int callbackResult = fx.EndInvoke(iar);
        }
        private int Demo53()
        {
        //定義一個Func<int,int>類型的委托 fx,功能:輸入一個整數,+100后輸出。 Func<int, int> fx = new Func<int, int>( x => { Console.WriteLine("Func<int, int>() Thread ID = " + Thread.CurrentThread.ManagedThreadId); return x + 100; } );

// BeginInvoke() 是異步調用,即在線程池中取一個新線程來執行 fx IAsyncResult iar = fx.BeginInvoke(28, CallbackFunc, "test param"); // do something....這里可以加入業務代碼 // 在回調方法執行完成前,此值是0。 return callbackResult; }

回調(callback)模式中, fx.BeginInvoke( )第二個參數對應的回調函數 CallbackFunc 的簽名必須符合

"void FuncName(IAsyncResult iar)" 的形式,最后一個參數是 object 類型,

可以傳入任意對象,在回調函數中用 iar.AsyncState 取值后做強制轉型就可以了(測試略)。

 

=================================分割線=================================

除了 async / await 和 delegate.BeginInvoke( ) / EndInvoke( ) 可以進行異步操作之外,

.net 還為我們提供了 System.Threading.Timer 、System.Threading.Tasks.Parallel 、

System.ComponentModel.BackgroundWorker 等類來做並行處理,

它們中部分更適用於GUI環境(如winform、WPF等),后續根據需要再做介紹。

 


免責聲明!

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



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