如何以非同步方式呼叫 Visual C# 方法

文章翻譯 文章翻譯
文章編號: 315582 - 檢視此文章適用的產品。
全部展開 | 全部摺疊

在此頁中

結論

Microsoft.NET Framework 方便非同步呼叫的函式。以非同步方式呼叫函式會導致系統時呼叫的函式會繼續執行其他工作在次要執行緒上背景中執行它們。在典型 (同步) 函式呼叫函式是立刻進行呼叫相同的執行緒上執行。呼叫函式等待呼叫完成,並接收在繼續進行前請先呼叫的結果。相反的當您進行非同步呼叫時,會擷取稍後在非同步呼叫的結果。本文將告訴您,如何執行這項操作藉由使用 Visual C#。

需求


下列清單列出建議的硬體、 軟體、 網路基礎結構及所需的 Service Pack:
  • Microsoft Windows 2000 或 Microsoft Windows XP Microsoft Windows Server 2003
  • Visual Studio.NET 或 Visual Studio 2005
本文假設您已熟悉下列主題:
  • 呼叫方法在 Visual C# 中
  • 如何使用委派

如何以進行非同步呼叫

非同步呼叫是使用委派來進行。委派是包裝函式的物件。委派提供同步的函式,而且也提供方法以非同步方式呼叫包裝函式。這些方法都是 BeginInvoke()EndInvoke()。這些方法的參數清單的委派包裝函式簽名碼而有所不同。請注意,Visual Studio.NET IntelliSense 功能不會顯示 BeginInvoke()EndInvoke()、 函式讓您執行不看到它們出現在列出當您輸入。

BeginInvoke() 用來初始化非同步呼叫。它擁有相同包裝函式的參數以及將在本文稍後說明的兩個額外參數。BeginInvoke() 立即傳回,並不會等待非同步呼叫完成。BeginInvoke() 傳回 IAsyncResult 物件。

EndInvoke() 函式用來擷取非同步呼叫的結果。可以隨時在 BeginInvoke() 之後呼叫。如果非同步呼叫尚未完成還,EndInvoke() 區塊直到完成為止。outref 參數包裝函式具有,加上 IAsyncResult 物件所傳回 BeginInvoke(),其中包括 EndInvoke() 函式的參數。

下列是委派,其 BeginInvoke()EndInvoke() 方法的範例:
// The following delegate 
delegate string MethodDelegate(int iCallTime, out int iExecThread)  ;

// will have the following BeginInvoke() and EndInvoke methods:
IAsyncResult MethodDelegate.BeginInvoke(int iCallTime, out int iExecThread, AsyncCallback cb, object AsyncState); 

string MethodDelegate.EndInvoke (out int iExecThread, IAsyncResult ar) ;
				
有四個常見的方式使用 BeginInvoke()EndInvoke() 來進行非同步呼叫。您呼叫 BeginInvoke() 之後,您可以:
  • 選擇性地執行一些其他工作,然後再使用 EndInvoke()
  • 取得 WaitHandle 所提供的 IAsyncResult 物件、 使用其 WaitOne 方法來封鎖,直到信號 WaitHandle 為止,然後呼叫 EndInvoke()
  • 輪詢來決定何時非同步呼叫完成,接著呼叫 EndInvoke()IAsyncResult 物件。
  • 讓系統呼叫您所指定的回呼函式。 這個回呼函式呼叫 EndInvoke(),並完成時處理非同步呼叫的結果。
下列程式碼範例將示範這些呼叫模式和對比與藉由使用下列的函式,讓同步呼叫:
string LongRunningMethod (int iCallTime, out int iExecThread)
{
	Thread.Sleep (iCallTime) ;
	iExecThread = AppDomain.GetCurrentThreadId ();
	return "MyCallTime was " + iCallTime.ToString() ;
}

				
LongRunningMethod() 模擬程式沈睡長時間執行的函式。它會傳回睡眠時間及執行它的執行緒 ID。如果您呼叫它以非同步方式,您會發現執行的執行緒的執行緒識別碼是不同於呼叫執行緒。

第一個步驟是定義包裝函式的委派:
delegate string MethodDelegate(int iCallTime, out int iExecThread)  ;
				

範例 1: 呼叫同步方法

這個範例會示範如何使用 MethodDelegate 委派,以同步方式呼叫 LongRunningMethod()。其他範例對比這以非同步方式進行呼叫。
  1. 啟動 Microsoft Visual Studio.NET 或 Microsoft Visual Studio 2005。
  2. 建立新的 Visual C# 主控台應用程式專案,名為 AsyncDemo。
  3. 加入一個名為 AsyncDemo 加入專案中,新的.cs 檔案,如下所示定義的類別:
    using System;
    using System.Threading ; 
    using System.Windows.Forms ;
    
    public class AsyncDemo
    {
    	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)  ;
    
    	public void DemoSyncCall()
    	{
    		string s ;
    		int iExecThread;
    
    		// Create an instance of a delegate that wraps LongRunningMethod.
    		MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;  
    			
    		// Call LongRunningMethod using the delegate.
    		s = dlgt(3000, out iExecThread);  
    			
    		MessageBox.Show (string.Format ("The delegate call returned the string:   \"{0}\", 
                                            and the thread ID {1}", s, iExecThread.ToString() ) );
    	}
    }
    					
    稍後,這個類別會示範如何進行非同步呼叫。 一開始,但是,它只包含示範如何同步呼叫委派的該 DemoSyncCall()] 方法。
  4. Visual Studio 會自動在您的專案中建立 Main 函式主體中加入下列程式碼:
    static void Main(string[] args)
    {
    	AsyncDemo ad = new AsyncDemo () ;
    	ad.DemoSyncCall() ;
    }
    					
  5. 按 CTRL + F5 執行您的應用程式。

範例 2: 呼叫方法以非同步方式使用 EndInvoke() 呼叫圖樣

本章節範例叫用非同步相同的方法。會使用此呼叫模式是呼叫 BeginInvoke,做一些在主執行緒上工作,然後呼叫 EndInvoke()。請注意 EndInvoke() 不會傳回直到非同步呼叫已經完成。這種呼叫模式很有用時您希望自己能夠呼叫的執行緒執行非同步呼叫的同時執行工作。在同一時間發生的工時,可以改善許多應用程式效能。這種方式以非同步方式執行的一般工作是檔案或網路作業。
  1. 加入名為 DemoEndInvoke()AsyncDemo 類別的方法。DemoEndInvoke 函式會示範如何以非同步方式呼叫委派。
    public void DemoEndInvoke()
    {
    	MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
    	string s ;
    	int iExecThread;
    
    	// Initiate the asynchronous call.
    	IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null);  
    
    	// Do some useful work here. This would be work you want to have
    	// run at the same time as the asynchronous call.
    
    	// Retrieve the results of the asynchronous call.
    	s = dlgt.EndInvoke (out iExecThread, ar) ;  
    
    	MessageBox.Show (string.Format ("The delegate call returned the string:   \"{0}\", 
                                   and the number {1}", s, iExecThread.ToString() ) );
    }
    					
  2. 編輯原始碼的 Main,讓它包含下列程式碼:
    static void Main(string[] args)
    {
    	AsyncDemo ad = new AsyncDemo () ;
    	ad.DemoEndInvoke() ;
    }
    					
  3. 按 CTRL + F5 執行您的應用程式。

範例 3: 以非同步方式呼叫方法,並且等待呼叫完成使用 A WaitHandle


本章節中範例以非同步方式呼叫方法,並等待 WaitHandle 之前呼叫 EndInvoke()。會傳回由 BeginInvoke()IAsyncResult 具有 AsyncWaitHandle 屬性。這個屬性會傳回非同步呼叫完成時,收到信號 WaitHandle。等候 WaitHandle 是一項常見的執行緒同步處理技巧。呼叫的執行緒會等候 WaitHandle 時請使用 WaitHandleWaitOne() 方法。WaitOne() 區塊直到 WaitHandle 收到信號為止。當 WaitOne() 傳回時,您可以在呼叫 EndInvoke() 之前執行一些額外的工作。為在先前的範例這項技巧非常有用的執行檔或網路否則會封鎖呼叫的主要執行緒的作業。
  1. 加入命名 AsyncDemo 類別的 DemoWaitHandle() 函式。DemoWaitHandle() 函式會示範如何以非同步方式呼叫委派。
    public void DemoWaitHandle ()
    {
    	string s ;
    	int iExecThread;
    
    	MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
    
    	// Initiate the asynchronous call.
    	IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null); 
    
    	// Do some useful work here. This would be work you want to have
    	// run at the same time as the asynchronous call.
    
    	// Wait for the WaitHandle to become signaled.
    	ar.AsyncWaitHandle.WaitOne() ;
    
    	// Get the results of the asynchronous call.
    	s = dlgt.EndInvoke (out iExecThread, ar) ;
    			
    	MessageBox.Show (string.Format ("The delegate call returned the string:   \"{0}\", 
                                     and the number {1}", s, iExecThread.ToString() ) );
    }
    					
  2. 編輯原始碼的 Main,讓它包含下列程式碼:
    static void Main(string[] args)
    {
    	AsyncDemo ad = new AsyncDemo () ;
    	ad.DemoWaitHandle () ;
    }
    					
  3. 按 CTRL + F5 執行您的應用程式。

範例 4: 呼叫方法以非同步方式使用輪詢呼叫模式

本章節範例會輪詢非同步呼叫完成時,找出 IAsyncResult 物件。IAsyncResult 物件所傳回 BeginInvoke() 具有 IsCompleted 屬性的非同步呼叫完成後會傳回 True。然後,您可以呼叫 EndInvoke()。這種呼叫模式如果會很有幫助您的應用程式不會持續不想長期執行的函式呼叫已封鎖的工作。Microsoft Windows 應用程式是這個範例。Windows 應用程式的主執行緒可以繼續處理使用者輸入,雖然非同步呼叫執行。它可以定期檢查 IsCompleted 來查看是否已完成呼叫。IsCompleted 傳回 True 時,它會呼叫 EndInvoke。因為 EndInvoke() 封鎖直到非同步作業完成,應用程式不會呼叫它直到它知道作業已完成。
  1. 加入命名 AsyncDemo 類別的 DemoPolling() 函式。DemoPolling() 函式示範如何以非同步方式呼叫委派,並使用輪詢來查看是否處理程序已完成。
    public void DemoPolling()
    {
    	MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
    	string s ;
    	int iExecThread;
    
    	// Initiate the asynchronous call.
    	IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null); 
    
    	// Poll IAsyncResult.IsCompleted
    	while(ar.IsCompleted == false)
    	{
    		Thread.Sleep (10) ;  // pretend to so some useful work
    	}
    	s = dlgt.EndInvoke (out iExecThread, ar) ;
    
    	MessageBox.Show (string.Format ("The delegate call returned the string:   \"{0}\", 
                                    and the number {1}", s, iExecThread.ToString() ) );
    }
    
    					
  2. 編輯 主要 原始程式檔。以下列程式碼取代函式的內容:
    static void Main(string[] args)
    {
    	AsyncDemo ad = new AsyncDemo () ;
    	ad.DemoPolling () ;
    }
    					
  3. 按 CTRL + F5 執行您的應用程式。

範例 5: 執行回呼,非同步方法完成時

本章節範例提供 BeginInvoke() 函式,系統會非同步呼叫完成時執行的回呼委派。回撥呼叫 EndInvoke() 並處理非同步呼叫的結果。這種呼叫模式如果會很有幫助啟始非同步呼叫的執行緒並不需要處理呼叫的結果。非同步呼叫完成時,系統會叫用初始執行緒以外的其他執行緒上回呼。

若要用以這種呼叫模式中,您必須傳遞 AsyncCallback 之型別的委派做為 BeginInvoke() 函式的第二個到最後一個參數。BeginInvoke() 也有最後一個參數的輸入到其中您可以將任何物件傳遞的 物件。當叫用時,這個物件是可使用回呼函式。這個參數的一個重要用途是將傳遞用來初始化呼叫的委派。回呼函式然後可以使用該委派的 EndInvoke() 函數來完成呼叫。這種呼叫模式也示範了下面。
  1. 新增命名 AsyncDemo 類別的 DemoCallback()MyAsyncCallback() 的兩個方法。DemoCallback() 方法示範如何以非同步方式呼叫委派。它會使用委派系統呼叫非同步作業完成時的將 MyAsyncCallback()] 方法包裝。MyAsyncCallback() 呼叫 EndInvoke()
    public void DemoCallback()
    {
    	MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
    	string s ;
    	int iExecThread;
    
    	// Create the callback delegate.
    	AsyncCallback cb = new AsyncCallback(MyAsyncCallback);
    
    	// Initiate the Asynchronous call passing in the callback delegate
    	// and the delegate object used to initiate the call.
    	IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, cb, dlgt); 
    }
    
    public void MyAsyncCallback(IAsyncResult ar)
    {
    	string s ;
    	int iExecThread ;
    
    	// Because you passed your original delegate in the asyncState parameter
    	// of the Begin call, you can get it back here to complete the call.
    	MethodDelegate dlgt = (MethodDelegate) ar.AsyncState;
    
    	// Complete the call.
    	s = dlgt.EndInvoke (out iExecThread, ar) ;
    
    	MessageBox.Show (string.Format ("The delegate call returned the string:   \"{0}\", 
                                    and the number {1}", s, iExecThread.ToString() ) );
    }
    
    					
  2. 編輯 主要 原始程式檔。以下列程式碼取代函式的內容:
    static void Main(string[] args)
    {
    	AsyncDemo ad = new AsyncDemo () ;
    	ad.DemoCallback() ;
    }
    					
  3. 按 CTRL + F5 執行您的應用程式。

屬性

文章編號: 315582 - 上次校閱: 2006年12月11日 - 版次: 4.3
這篇文章中的資訊適用於:
  • Microsoft Visual Studio .NET 2002 Professional Edition
  • Microsoft Visual C# .NET 2002 Standard Edition
  • Microsoft Visual C# 2005 Express Edition
關鍵字:?
kbmt kbhowtomaster KB315582 KbMtzh
機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:315582
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。

提供意見

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com