1. 程式人生 > >c#使用委託實現非同步呼叫

c#使用委託實現非同步呼叫

非同步程式設計是受公共語言執行庫的許多領域(如遠端處理、ASP.NET 和 Windows 窗體)支援的功能。非同步程式設計是 .NET Framework 中的核心概念。使用 .NET 非同步程式設計,在程式繼續執行的同時對 .NET 類方法進行呼叫,直到進行指定的回撥為止;或者如果沒有提供回撥,則直到對呼叫的阻塞、輪詢或等待完成為止。

非同步程式設計是由 .NET Framework 的許多區域支援的功能,這些區域包括:

  • 檔案 IO、流 IO、套接字 IO
  • 網路:HTTP、TCP
  • 遠端處理通道(HTTP、TCP)和代理
  • 使用 ASP.NET 建立的 XML Web services
  • ASP.NET Web 窗體
  • 使用 MessageQueue 類的訊息佇列
  • 非同步委託

.NET Framework 允許非同步呼叫任何方法。定義與需要呼叫的方法具有相同簽名的委託;公共語言執行庫將自動為該委託定義具有適當簽名的 BeginInvokeEndInvoke 方法。

  1. BeginInvoke 方法用於啟動非同步呼叫。它與需要非同步執行的方法具有相同的引數,只不過還有兩個額外的引數(將在稍後描述)。BeginInvoke 立即返回,不等待非同步呼叫完成。BeginInvoke 返回 IasyncResult,可用於監視呼叫進度。
  2. EndInvoke
    方法用於檢索非同步呼叫結果。呼叫 BeginInvoke 後可隨時呼叫 EndInvoke 方法;如果非同步呼叫未完成,EndInvoke 將一直阻塞到非同步呼叫完成。EndInvoke 的引數包括需要非同步執行的方法的 outref 引數以及由 BeginInvoke 返回的 IAsyncResult

呼叫了 BeginInvoke 後,可以:

  • 進行某些操作,然後呼叫 EndInvoke 一直阻塞到呼叫完成。
  • 使用 IAsyncResult.AsyncWaitHandle 獲取 WaitHandle,使用它的 WaitOne 方法將執行一直阻塞到發出 WaitHandle
    訊號,然後呼叫 EndInvoke
  • 輪詢由 BeginInvoke 返回的 IAsyncResult,確定非同步呼叫何時完成,然後呼叫 EndInvoke
  • 將用於回撥方法的委託傳遞給 BeginInvoke。該方法在非同步呼叫完成後在 ThreadPool 執行緒上執行,它可以呼叫 EndInvoke。  

下面是一個使用委託呼叫非同步方法的例子。例項中首先定義了一個AddDelegate型別委託add,並將方法Add繫結到委託例項上。然後定義了IAsyncResult介面型別例項iAR並呼叫委託add的BeginInvoke方法用於啟動非同步呼叫。由於非同步呼叫完成時會發出 WaitHandle 訊號,因此可以通過iAR.AsyncWaitHandle.WaitOne();來等待它,在這期間主程式可以執行一些其他的任務以達到程式非同步執行的效果。最後呼叫EndInvoke 方法用於檢索非同步呼叫結果。值得注意的是如果非同步呼叫未完成,EndInvoke 將一直阻塞到非同步呼叫完成。

using System;
using System.Threading;

//使用委託呼叫非同步方法的例子
namespace DelegateCallAsynchronousMethods
{

    
class AsyncDelegatesBlocked
    
{
        
publicstaticint Add(int op1, int op2, outint result)
        
{
            Thread.Sleep(
3000); // Simulating work
return (result = op1 + op2);
        }

        
publicdelegateint AddDelegate(int op1, int op2,
            
outint result);//宣告AddDelegate委託

        
staticvoid Main()
        
{
            
int result;
            
/*定義一個AddDelegate型別委託add,將方法Add繫結到委託例項上*/
            AddDelegate add 
=new AddDelegate(Add);

            Console.WriteLine(
"[Main] Invoking the asynchronous "+
                
"Add method");

            
/*BeginInvoke 方法用於啟動非同步呼叫。它與您需要非同步執行的方法具有相同的引數,還有兩個額外的引數
             *BeginInvoke 立即返回,不等待非同步呼叫完成。BeginInvoke 返回 IasyncResult,可用於監視呼叫進度。
*/

            
            
//定義IAsyncResult介面型別例項iAR
            
//6, 42, out result為非同步執行的方法的引數列表
            IAsyncResult iAR = add.BeginInvoke(642out result,  
                
nullnull);

            
// Here we're simulating doing some work before
            
// blocking on the Add method's completion.
            Console.Write("[Main] Doing other work");
            
for (int i =0; i <10; i++
            
{
                Thread.Sleep(
200);
                Console.Write(
".");
            }


            Console.WriteLine(
" [Main] Waiting for Add to finish");
            
/*使用 IAsyncResult.AsyncWaitHandle 獲取 WaitHandle,
             * 使用它的 WaitOne 方法將執行一直阻塞到發出 WaitHandle 訊號,然後呼叫 EndInvoke。
             * 注意:非同步呼叫完成時會發出 WaitHandle 訊號,可以通過WaitOne 來等待它
*/

            iAR.AsyncWaitHandle.WaitOne(); 

            Console.WriteLine(
"[Main] Add finished, cleaning up");
            
/*EndInvoke 方法用於檢索非同步呼叫結果。呼叫 BeginInvoke 後可隨時呼叫 EndInvoke 方法;
             * 如果非同步呼叫未完成,EndInvoke 將一直阻塞到非同步呼叫完成。
             * EndInvoke 的引數包括所需要非同步執行的方法的 out 和 ref 引數以及由 BeginInvoke 返回的 IAsyncResult。
*/

            add.EndInvoke(
out result, iAR);

            Console.WriteLine(
"[Main] The result is {0}", result);
            Console.ReadLine();
        }

    }
;

}