1. 程式人生 > >非同步程式設計(AsyncCallback委託,IAsyncResult介面,BeginInvoke方法,EndInvoke方法的使用小結)

非同步程式設計(AsyncCallback委託,IAsyncResult介面,BeginInvoke方法,EndInvoke方法的使用小結)

(一)讓我們來看看同步非同步的區別

同步方法呼叫在程式繼續執行之前需要等待同步方法執行完畢返回結果。

非同步方法則在被呼叫之後立即返回以便程式在被呼叫方法完成其任務的同時執行其它操作。

.NET框架基類庫中有好幾種類都可以提供同步和非同步的方法呼叫。

因為同步方法呼叫會導致程式流程中途等待,所以採用同步方法的情況下往往會導致程式執行的延遲,相比來說,在某些條件下選擇非同步方法呼叫就可能更好一些。

例如:有的時候程式需要給多個Web服務發出請求,還有遠端處理通道(HTTP、TCP)和代理,這時就最好採用非同步方法。

.NET Framework允許非同步呼叫任何方法,定義與需要呼叫的方法具有相同簽名的委託。CLR將自動為該委託定義新增適當簽名的BeginInvoke虛方法和EndInvoke虛方法和Invoke方法。

(二) 我們先來了解這2個方法和一個委託和一個介面

(1)BeginInvoke方法可啟動非同步呼叫。

它與您需要非同步執行的方法具有相同的引數,另外它還有兩個可選引數。第一個引數是一個AsyncCallback 委託,該委託引用在非同步呼叫完成時要呼叫的方法。第二個引數是一個使用者定義的物件,該物件可向回撥方法傳遞資訊。BeginInvoke立即返回,不等待非同步呼叫完成。BeginInvoke 會返回 IAsyncResult,這個結果可用於監視非同步呼叫進度。

結果物件IAsyncResult是從開始操作返回的,並且可用於獲取有關非同步開始操作是否已完成的狀態。結果物件被傳遞到結束操作,該操作返回呼叫的最終返回值。在開始操作中可以提供可選的回撥。如果提供回撥,在呼叫結束後,將呼叫該回調;並且回撥中的程式碼可以呼叫結束操作。

(2)EndInvoke方法檢索非同步呼叫的結果。

呼叫 BeginInvoke 後可隨時呼叫 EndInvoke方法;如果非同步呼叫尚未完成,EndInvoke 將一直阻止呼叫執行緒,直到非同步呼叫完成後才允許呼叫執行緒執行。EndInvoke 的引數包括您需要非同步執行的方法的 out 和 ref 引數以及由BeginInvoke 返回的 IAsyncResult。

(3)AsyncCallback委託用於指定在開始操作完成後應被呼叫的方法

AsyncCallback委託被作為開始操作上的第二個到最後一個引數傳遞。

程式碼原型如下:

[Serializable]

publicdelegate void AsyncCallback(IAsyncResult ar);

AsyncCallback為客戶端應用程式提供完成非同步操作的方法。開始非同步操作時,該回調委託被提供給客戶端。AsyncCallback引用的事件處理程式包含完成客戶端非同步任務的程式邏輯。

AsyncCallback使用 IAsyncResult 介面獲取非同步操作的狀態。

(4)IAsyncResult介面

它表示非同步操作的狀態.該介面定義了4個公用屬性。

程式碼原型如下:

publicinterface IAsyncResult

(三) 控制檯原始碼

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace AsyncStudy
{
    class Program
    {
        static void Main(string[] args)
        {
            DemoSyncCall(); //示例 1
            //DemoEndInvoke();//示例 2
            //DemoWaitHandle();//示例 3
            //DemoPolling();//示例 4
            //DemoCallback();//示例 5
            Console.ReadLine();
        }

        /// <summary>
        /// 實現委託的方法
        /// </summary>
        /// <param name="iCallTime"></param>
        /// <param name="iExecThread"></param>
        /// <returns></returns>
        public static string LongRunningMethod(int iCallTime, out int iExecThread)
        {
            Thread.Sleep(iCallTime);
            iExecThread = AppDomain.GetCurrentThreadId();
            return "MyCallTime was:" + iCallTime.ToString();
        }

        delegate string MethodDelegate(int iCallTime, out int iExecThread);

        #region 示例 1: 同步呼叫方法
        /// <summary>
        /// 同步呼叫方法
        /// </summary>
        public static void DemoSyncCall()
        {
            string str;
            int iExecThread;
            MethodDelegate md = new MethodDelegate(LongRunningMethod);
            str = md(3000, out iExecThread);
            Console.WriteLine("the Delegate call returned string:{0},and the thread ID is:{1}", str, iExecThread.ToString());
            //sara Bareilles
        }
        #endregion

        #region 示例 2: 通過EndInvoke()呼叫模式非同步呼叫模式
        /*
         * 使用呼叫模式是要呼叫 BeginInvoke , 做某些處理主執行緒, 並呼叫 EndInvoke() 。 
         * 注意不 EndInvoke() 不返回直到非同步呼叫已完成。 
         * 此呼叫模式是有用當要有呼叫執行緒正在執行非同步呼叫, 同時工作。 
         * 有同時發生工作可改善許多應用程式的效能。 
         * 常見任務以非同步執行以此方式是檔案或網路操作。 
         * */
        /// <summary>
        /// 通過EndInvoke()呼叫模式非同步呼叫模式
        /// </summary>
        public static void DemoEndInvoke()
        {
            string str;
            int iExecTread;
            MethodDelegate dlgt = new MethodDelegate(LongRunningMethod);
            IAsyncResult iar = dlgt.BeginInvoke(5000, out iExecTread, null, null);
            str = dlgt.EndInvoke(out iExecTread, iar);
            Console.WriteLine("the Delegate call returned string:{0},and the number is:{1}", str, iExecTread.ToString());
        }
        #endregion
        #region  示例 3:非同步呼叫方法並使用 A WaitHandle 來等待呼叫完成
        /*
         * 由 BeginInvoke() 返回 IAsyncResult 具有一個 AsyncWaitHandle 屬性。 
         * 該屬性返回 WaitHandle 非同步呼叫完成後, 通知是。 等待 WaitHandle 是常見執行緒同步技術。 
         * 通過是 WaitHandle WaitOne() 方法呼叫執行緒等待 WaitHandle 上。 
         * 直到是通知 WaitHandle WaitOne() 塊。 當 WaitOne() 返回, 您在呼叫 EndInvoke() 之前進行一些額外工作。 
         * 對於執行檔案或網路操作, 否則會阻塞呼叫主執行緒存為, 以前示例中此技術很有用。
         * */
        /// <summary>
        /// 非同步呼叫方法並使用 A WaitHandle 來等待呼叫完成
        /// </summary>
        public static void DemoWaitHandle()
        {
            string str;
            int iExecTread;
            MethodDelegate dlgt = new MethodDelegate(LongRunningMethod);
            IAsyncResult iar = dlgt.BeginInvoke(3000, out iExecTread, null, null);
            iar.AsyncWaitHandle.WaitOne();
            str = dlgt.EndInvoke(out iExecTread, iar);
            Console.WriteLine("the Delegate call returned string:{0},and the number is:{1}", str, iExecTread.ToString());
        }
        #endregion
        #region 示例 4: 非同步呼叫方法通過輪詢呼叫模式
        /*
         * 由 BeginInvoke() 返回 IAsyncResult 物件有個 IsCompleted 屬性非同步呼叫完成後返回 True 。 
         * 然後可呼叫 EndInvoke() 。 如果您應用程式不斷工作對不做要長期函式呼叫已被此呼叫模式很有用。 
         * MicrosoftWindows 應用程式是這樣的示例。 
         * 主執行緒的 Windows 應用程式可以繼續以執行非同步呼叫時處理使用者輸入。 
         * 它可定期檢查 IsCompleted 到呼叫是否完成。 它呼叫 EndInvoke 當 IsCompleted 返回 True 。 
         * 直到它知道操作已完成因為 EndInvoke() 阻止直到非同步操作為完整, 應用程式不呼叫它。 
         * */
        /// <summary>
        ///  非同步呼叫方法通過輪詢呼叫模式
        /// </summary>
        public static void DemoPolling()
        {
            string str;
            int iExecThread;
            MethodDelegate dlgt = new MethodDelegate(LongRunningMethod);
            IAsyncResult iar = dlgt.BeginInvoke(3000, out iExecThread, null, null);
            while(iar.IsCompleted==false)
            {
                Thread.Sleep(10);
            }
            str = dlgt.EndInvoke(out iExecThread, iar);
            Console.WriteLine("the Delegate call returned string:{0},and the number is:{1}", str, iExecThread.ToString());
        }
        #endregion

        #region 示例 5: 非同步方法完成後執行回撥
        /*
         * 本節, 中示例提供對 BeginInvoke() 函式, 非同步呼叫完成後系統執行回撥委託。 
         * 回撥呼叫 EndInvoke() 並處理非同步呼叫的結果。 
         * 如果啟動非同步呼叫執行緒不需要處理結果是呼叫此呼叫模式很有用。 
         * 非同步呼叫完成後系統呼叫執行緒以外啟動執行緒上調。 
         * 若使用此呼叫模式, 作為第二到最後 - BeginInvoke() 函式的引數必須傳遞 AsyncCallback 型別的委託。 
         * BeginInvoke() 還有最後引數鍵入 物件 到您可以將任何物件。 當它呼叫該物件可用於您回撥函式。 
         * 為此引數一個重要用途是以傳遞用於初始化呼叫該委託。 
         * 回撥函式然後使用與該委託 EndInvoke() 函式來完成呼叫。 此呼叫模式是所示。
         * */
        /// <summary>
        /// 非同步方法完成後執行回撥
        /// </summary>
        public static void DemoCallback()
        {
            MethodDelegate dlgt = new MethodDelegate(LongRunningMethod);
            int iExecThread;
            AsyncCallback asyncCallback = new AsyncCallback(MyAsyncCallback);
            IAsyncResult iar = dlgt.BeginInvoke(5000,out iExecThread, asyncCallback, dlgt);
        }

        /// <summary>
        ///  非同步方法完成後執行回撥
        /// </summary>
        /// <param name="iar"></param>
        public static void MyAsyncCallback(IAsyncResult iar)
        {
            string str;
            int iExecThread;
            MethodDelegate dlgt = (MethodDelegate)iar.AsyncState;
            str = dlgt.EndInvoke(out iExecThread, iar);
            Console.WriteLine("the Delegate call returned string:{0},and the number is:{1}", str, iExecThread.ToString());
        }
        #endregion
    }
}


(四)總結

四種使用BeginInvoke和EndInvoke進行非同步呼叫的常用方法。在呼叫BeginInvoke 之後,可以執行下列操作:

1.進行某些操作,然後呼叫 EndInvoke 一直阻止到呼叫完成。

2.使用 System.IAsyncResult.AsyncWaitHandle 屬性獲取 WaitHandle,使用它的 WaitOne 方法一直阻止執行直到發出 WaitHandle 訊號,然後呼叫 EndInvoke。

3.輪詢由 BeginInvoke 返回的 IAsyncResult,確定非同步呼叫何時完成,然後呼叫 EndInvoke。

4.將用於回撥方法的委託傳遞給 BeginInvoke。非同步呼叫完成後,將在ThreadPool 執行緒上執行該方法。該回調方法將呼叫 EndInvoke。

注意: 每次都要呼叫EndInvoke來完成非同步呼叫。

相關推薦

非同步程式設計(AsyncCallback委託,IAsyncResult介面,BeginInvoke方法,EndInvoke方法的使用小結)

(一)讓我們來看看同步非同步的區別 同步方法呼叫在程式繼續執行之前需要等待同步方法執行完畢返回結果。 非同步方法則在被呼叫之後立即返回以便程式在被呼叫方法完成其任務的同時執行其它操作。 .NET框架基類庫中有好幾種類都可以提供同步和非同步的方法呼叫。 因為同步方法呼叫會導致

非同步使用委託delegate --- BeginInvokeEndInvoke方法

當我們定義一個委託的時候,一般語言執行時會自動幫委託定義BeginInvoke 和 EndInvoke兩個方法,這兩個方法的作用是可以非同步呼叫委託。 方法BeginInvoke有兩個引數: AsyncCallBack:回撥函式,是一個委託,沒有返回值,可以傳一個引數,引數型別是object;

C# 多執行緒 用委託實現非同步_呼叫委託BeginInvokeEndInvoke方法

1.C#中的每一個委託都內建了BeginInvoke和EndInvoke方法,如果委託的方法列表裡只有一個方法,那麼這個方法就可以非同步執行(不在當前執行緒裡執行,另開闢一個執行緒執行)。委託的BeginInvoke和EndInvoke方法就是為了上述目的而生的。 2.原始

非同步程式設計委託

前言: 專案中由於大量的資料讀取操作,導致每次載入介面都需要長時間等待,因此決定使用非同步來獲取資料,實現更好的使用者體驗。 趁此機會,也好好的補充一下自己在非同步程式設計方面的知識! 先從委託開始說起! 委託的定義: 委託是一個類,它定義了方法的型別,使得可以將方法當作另一個方法的引數來進行傳遞。 委託的特

[C#學習筆記之異步編程模式2]BeginInvokeEndInvoke方法 (轉載)

cti otf 函數返回 編程模式 catch 數值 gin 單線程 blog 為什麽要進行異步回調?眾所周知,普通方法運行,是單線程的,如果中途有大型操作(如:讀取大文件,大批量操作數據庫,網絡傳輸等),都會導致方法阻塞,表現在界面上就是,程序卡或者死掉,界面元素不動了,

C#執行緒系列講座(1):BeginInvokeEndInvoke方法

開發語言:C#3.0 IDE:Visual Studio 2008 本系列教程主要包括如下內容:1.  BeginInvoke和EndInvoke方法 2.  Thread類 3. 執行緒池 4. 執行緒同步基礎 5. 死鎖 6. 執行

BeginInvokeEndInvoke方法

開發語言:C#3.0 IDE:Visual Studio 2008 本系列教程主要包括如下內容: 1.  BeginInvoke和EndInvoke方法 2.  Thread類 3. 執行緒池 4. 執行緒同步基礎 5. 死鎖 6. 執行緒同步的7種方法

JS非同步程式設計的四種方法

一、回撥函式,這是非同步程式設計最基本的方法 假定有兩個函式f1和f2,後者等待前者的執行結果,如果f1是一個很耗時的任務,可以考慮改寫f1,把f2寫成f1的回撥函式。 function f1(callback){   setTimeout(function () {    //

javascript實現非同步程式設計的4種方法

1、回撥函式。 2、事件監聽 。  思路:採用事件驅動模式。任務的執行不取決於程式碼的順序,而取決於某個事件是否發生 3、觀察者模式 (釋出/訂閱模式)   程式碼如下: jQuery.subscribe("done", f2);  function f1(){

AsyncCallback AsyncCallback 非同步回撥委託

  AsyncCallback 非同步回撥委託 AsyncCallback 意義: 非同步操作完成時呼叫的方法 語法1: 構造非同步回撥物件 AsyncCallbac

併發程式設計----介面聚合 (實現方法

 併發程式設計 1.在Service中實現多執行緒的返回結果聚合,例如下圖 分三個執行緒,執行緒1、執行緒2、執行緒3來現實使用者資訊系統、使用者餘額系統、使用者積分系統 最後進行返回結果聚合  2。在使用多執行緒的情況下,繼續使用執行緒池來實現減少執行時間。

C#非同步程式設計2:非同步方法

一、非同步方法描述:         1、非同步方法結構                            

C# 使用委託實現非同步程式設計的四種方式

一、關於委託 1、委託概念:委託是一個類,它定義了方法的型別,使得可以將方法當作另一個方法的引數來進行傳遞      個人角色這個概念有些晦澀難懂,大家可以把委託當成一個方法的指標就好了,可以指向一個方法。或者通過(+=)的方式指向多個。 2、四種宣告方式 1)直接用del

ES6---JS非同步程式設計的幾種解決方法及其優缺點

前言 因專案需要從LiveScript轉為ES6, 所以最近看了阮一峰的ES6教程,主要感興趣的是ES6對JS的非同步程式設計新的解決方案,ES6增加了promise和Generator等解決方法。現在我們來大致理清一下到ES6為止的JS非同步解決的思路

Javascript非同步程式設計四種方法

這種模式的好處是實現起來比較簡單,執行環境相對單純;壞處是隻要有一個任務耗時很長,後面的任務都必須排隊等著,會拖延整個程式的執行。常見的瀏覽器無響應(假死),往往就是因為某一段Javascript程式碼長時間執行(比如死迴圈),導致整個頁面卡在這個地方,其他

php 介面併發測試的方法

PHP介面併發測試的方法              header('Content-type:text/html; Charset=utf-8');           &nb

Scala 非同步程式設計之 Future (二)

上篇部落格講了scala中的Future,實際上java 在jdk1.5後增加了callable,也實現了Future,以《Netty In Action》中的程式碼為例,看一下java中Future的實現: import java.util.concurrent.Callable; im

Scala 非同步程式設計之 Future

同步非同步,阻塞非阻塞,在IO模型中幾個概念組合在一起不是很容易理解,但是隻從程式碼執行的角度看同步非同步是很清晰的: 同步代表這段程式碼中的邏輯必須執行完畢,而非同步代表呼叫馬上返回,但通常情況下是獲取不到需要的值。 同步:val  value={ Thread.sleep(

Dart非同步程式設計之Stream

Dart非同步程式設計包含兩部分:Future和Stream 上篇文章已介紹了Future,此篇文章為大家介紹下另一塊–Stream Dart 非同步事件流 Stream 基本概念 顧名思義,Stream 就是流的意思,表示發出的一系列的非同步資料。可以簡單地認為 Strea

Dart非同步程式設計之Future

Dart非同步程式設計包含兩部分:Future和Stream 本文將詳細介紹Future Dart非同步程式設計-future 非同步程式設計:Futures Dart是一個單執行緒程式語言。如果任何程式碼阻塞執行緒執行都會導致程式卡死。非同步程式設計防止出現阻塞操作。Dar