非同步

非同步範例示範用戶端如何非同步存取服務作業,以及服務如何非同步實作其作業。這個範例是以實作計算機服務的使用者入門範例為基礎。使用同步或非同步叫用是本機決策,不影響網路上傳送的訊息。雖然服務會實作一些同步作業,用戶端還是可以非同步存取服務作業。即使用戶端同步呼叫服務,服務仍然可以非同步實作某些作業。

ms751505.note(zh-tw,VS.90).gif注意:
要建置和執行這個範例,必須安裝 .NET Framework version 3.5。要開啟專案和方案檔,必須要有 Visual Studio 2008。

ms751505.note(zh-tw,VS.90).gif注意:
此範例的安裝程序與建置指示位於本主題的結尾。

在這個範例中,用戶端是主控台應用程式 (.exe),而服務則會在主控台應用程式 (.exe) 中自我裝載。

服務會實作 ICalculator 介面。用戶端可以在這個介面上非同步呼叫作業,即表示像 Add 這樣的作業現在會有 BeginAddEndAdd

ms751505.note(zh-tw,VS.90).gif注意:
如需非同步模式的詳細資訊,請參閱 .NET Framework 文件。

用戶端已產生支援這些非同步作業的程式碼。用戶端是藉由執行 Service Metadata Utility Tool (Svcutil.exe) 工具搭配 /a (async) 命令選項所建立,如下所示:

svcutil /n:http://Microsoft.ServiceModel.Samples,Microsoft.ServiceModel.Samples https://localhost:8000/servicemodelsamples/service/mex /a /tcv:Version35

Add 作業之服務合約的非同步用戶端版本看起來會像下列程式碼。

[System.ServiceModel.ServiceContractAttribute(Namespace=
                   "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
    [System.ServiceModel.OperationContractAttribute(
       AsyncPattern=true)]
    System.IAsyncResult BeginAdd(double n1, double n2, 
                   System.AsyncCallback callback, object asyncState);
    double EndAdd(System.IAsyncResult result);
    
    ...
}

同時指定 /tcv:Version35 選項與 /async 選項時,產生的用戶端類型便會實作事件架構非同步模式來呼叫服務。如需詳細資訊,請參閱事件架構非同步模式概觀 (本頁面可能為英文)。若要以非同步方式存取服務作業,應用程式會將事件處理常式新增至用戶端上的 [Operation]Completed 事件,然後再呼叫 [Operation]Async 方法 (例如,AddAsync),如下列所示範例程式碼。

// Create a client.
CalculatorClient client = new CalculatorClient();

// BeginAdd.
double value1 = 100.00D;
double value2 = 15.99D;

client.AddCompleted += new EventHandler<AddCompletedEventArgs>(AddCallback);
client.AddAsync(value1, value2);

在範例中,用戶端非同步啟動兩項作業:AddSubtract

當回呼函式執行時,用戶端便會存取 [Operation]CompletedEventArgs 輸入參數上的 Result 屬性以擷取結果。

static void AddCallback(object sender, AddCompletedEventArgs e)
{
 Console.WriteLine("Add Result: {0}", e.Result);
}

所有非同步行為都是在用戶端本機發生,與訊息是從用戶端傳送或是由服務處理無關。在使用者介面 (UI) 應用程式中使用這種模式的一般原因是,要讓 UI 執行緒隨時可供更新畫面之用。當服務做為用戶端,而您想要從對其他服務的呼叫中釋放訊息處理執行緒時,也適用這種模式。下一節將示範如何進行非同步服務作業。

服務會實作 ICalculator 介面,如下列程式碼所示。

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
    [OperationContract]
    double Add(double n1, double n2);
    
    [OperationContract]
    double Subtract(double n1, double n2);
    
    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginMultiply(double n1, double n2,
        AsyncCallback callback, object state);
    double EndMultiply(IAsyncResult ar);

    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginDivide(double n1, double n2, 
        AsyncCallback callback, object state);
    double EndDivide(IAsyncResult ar); 
}

合約的前兩項作業會由 Windows Communication Foundation (WCF) 執行階段同步叫用。最後兩組成對的作業是用來非同步叫用服務。此範例將 AsyncPattern 屬性設定為 true。這項屬性設定與 .NET Framework 非同步模式實作搭配使用時,會指示執行階段以非同步方式叫用作業。

在服務實作中使用這個模式的原因通常是,要在執行耗時的輸入和輸出作業 (如存取磁碟、存取資料庫,或呼叫其他服務) 時,釋放訊息處理執行緒。這個範例示範如何將檔案輸入和輸出作業與 IAsyncResult 的實作包裝在一起。您可以重複使用 MathAsyncResult 類別的實作基底類別,來撰寫自己的 IAsyncResult 實作。

ms751505.note(zh-tw,VS.90).gif注意:
這個範例會使用 PerCallMultiple,以避免產生伴隨工作階段繫結的順序行為。根據預設,wsHttpBinding 會使用工作階段來建立安全性內容。這不會在用戶端或服務上影響訊息處理的非同步性質,卻能強調對於回應時機的說明,而且可讓用戶端觀察到並行的 (而非序列的) 回呼。

當您執行範例時,作業的要求和回應會顯示在用戶端主控台視窗中。因為是以非同步方式叫用,所以 AddSubtract 要求不會封鎖起來。接著,MultiplyDivide 作業會封鎖,而其結果則在送出要求的同時顯示。最後,來自 AddSubtract 作業的結果會在結果返回到用戶端時顯示。在 AddSubtract 的服務實作中,會使用 sleep 將非同步回呼顯示在用戶端。

Add(100,15.99)
Subtract(145,76.54)
Multiply(9,81.25) = 731.25
Divide(22,7) = 3.14285714285714
Add Result: 115.99
Subtract Result: 68.46

在服務上使用執行緒識別碼來示範如何在單一執行緒中處理同步呼叫 (例如 AddSubtract)。非同步呼叫 (例如 MultiplyDivide) 包含一個以上的執行緒。服務輸出如下所示。

Received Add Synchronously on ThreadID 11:  Sleeping for 3 seconds
Asynchronous call: BeginMultiply on ThreadID 12
Received Subtract Synchronously on ThreadID 12:  Sleeping for 3 seconds
IO thread for * operation on ThreadID 13
EndMultiply called on ThreadID 14
Asynchronous call: BeginDivide on ThreadID 14
IO thread for / operation on ThreadID 13
EndDivide called on ThreadID 14
Returning Add Result on ThreadID 11
Returning Subtract Result on ThreadID 12

.NET Framework 非同步模式可以用於用戶端、伺服器,或同時用於兩者。如本範例所示,這兩端都是各自獨立的。

若要設定、建置及執行範例

  1. 請確定您已執行 Windows Communication Foundation 範例的單次安裝程序

  2. 若要建置方案的 C# 或 Visual Basic .NET 版本,請遵循建置 Windows Communication Foundation 範例中的指示。

  3. 若要在單一或跨電腦的組態中執行本範例,請遵循執行 Windows Communication Foundation 範例中的指示。

Send comments about this topic to Microsoft.
© 2007 Microsoft Corporation. All rights reserved.