Cara: Memanggil Operasi Layanan WCF Secara Asinkron
Artikel ini membahas bagaimana klien dapat mengakses operasi layanan secara asinkron. Layanan dalam artikel ini mengimplementasikan antarmuka ICalculator
. Klien dapat memanggil operasi pada antarmuka ini secara asinkron dengan menggunakan model panggilan asinkron berbasis peristiwa. (Untuk informasi selengkapnya tentang model panggilan asinkron berbasis peristiwa, lihat Pemrograman Multithreaded dengan Pola Asinkron berbasis Peristiwa). Untuk contoh yang menunjukkan cara menerapkan operasi secara asinkron dalam layanan, lihat Cara: Menerapkan Operasi Layanan Asinkron. Untuk informasi selengkapnya tentang operasi sinkron dan asinkron, lihat Operasi Sinkron dan Asinkron.
Catatan
Model panggilan asinkron berbasis peristiwa tidak didukung saat menggunakan ChannelFactory<TChannel>. Untuk informasi tentang melakukan panggilan asinkron menggunakan ChannelFactory<TChannel>, lihat Cara: Memanggil Operasi Secara Asinkron Menggunakan Pabrik Saluran.
Prosedur
Untuk memanggil operasi Layanan WCF secara asinkron
Jalankan alat Alat Utilitas Metadata ServiceModel (Svcutil.exe) dengan opsi perintah
/async
dan/tcv:Version35
bersama-sama seperti yang ditunjukkan pada perintah berikut.svcutil /n:http://Microsoft.ServiceModel.Samples,Microsoft.ServiceModel.Samples http://localhost:8000/servicemodelsamples/service/mex /a /tcv:Version35
Ini menghasilkan, selain operasi asinkron berbasis delegasi sinkron dan standar, kelas klien WCF yang berisi:
Dua operasi <
operationName
>Async
untuk digunakan dengan pendekatan panggilan asinkron berbasis peristiwa. Misalnya:public void AddAsync(double n1, double n2) { this.AddAsync(n1, n2, null); } public void AddAsync(double n1, double n2, object userState) { if ((this.onBeginAddDelegate == null)) { this.onBeginAddDelegate = new BeginOperationDelegate(this.OnBeginAdd); } if ((this.onEndAddDelegate == null)) { this.onEndAddDelegate = new EndOperationDelegate(this.OnEndAdd); } if ((this.onAddCompletedDelegate == null)) { this.onAddCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnAddCompleted); } base.InvokeAsync(this.onBeginAddDelegate, new object[] { n1, n2}, this.onEndAddDelegate, this.onAddCompletedDelegate, userState); }
Public Overloads Sub AddAsync(ByVal n1 As Double, ByVal n2 As Double) Me.AddAsync(n1, n2, Nothing) End Sub Public Overloads Sub AddAsync(ByVal n1 As Double, ByVal n2 As Double, ByVal userState As Object) If (Me.onBeginAddDelegate Is Nothing) Then Me.onBeginAddDelegate = AddressOf Me.OnBeginAdd End If If (Me.onEndAddDelegate Is Nothing) Then Me.onEndAddDelegate = AddressOf Me.OnEndAdd End If If (Me.onAddCompletedDelegate Is Nothing) Then Me.onAddCompletedDelegate = AddressOf Me.OnAddCompleted End If MyBase.InvokeAsync(Me.onBeginAddDelegate, New Object() {n1, n2}, Me.onEndAddDelegate, Me.onAddCompletedDelegate, userState) End Sub
Operasi melengkapi peristiwa formulir <
operationName
>Completed
untuk digunakan dengan pendekatan panggilan asinkron berbasis peristiwa. Misalnya:public event System.EventHandler<AddCompletedEventArgs> AddCompleted;
Public Event AddCompleted As System.EventHandler(Of AddCompletedEventArgs)
System.EventArgs jenis untuk setiap operasi (dari formulir <
operationName
>CompletedEventArgs
) untuk digunakan dengan pendekatan panggilan asinkron berbasis peristiwa. Misalnya:[System.Diagnostics.DebuggerStepThroughAttribute()] [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")] public partial class AddCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { private object[] results; public AddCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : base(exception, cancelled, userState) { this.results = results; } public double Result { get { base.RaiseExceptionIfNecessary(); return ((double)(this.results[0])); } } }
<System.Diagnostics.DebuggerStepThroughAttribute(), _ System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")> _ Partial Public Class AddCompletedEventArgs Inherits System.ComponentModel.AsyncCompletedEventArgs Private results() As Object Public Sub New(ByVal results() As Object, ByVal exception As System.Exception, ByVal cancelled As Boolean, ByVal userState As Object) MyBase.New(exception, cancelled, userState) Me.results = results End Sub Public ReadOnly Property Result() As Double Get MyBase.RaiseExceptionIfNecessary Return CType(Me.results(0),Double) End Get End Property End Class
Dalam aplikasi panggilan, buat metode panggilan balik untuk dipanggil ketika operasi asinkron selesai, seperti yang ditunjukkan dalam kode sampel berikut.
// Asynchronous callbacks for displaying results. static void AddCallback(object sender, AddCompletedEventArgs e) { Console.WriteLine("Add Result: {0}", e.Result); }
' Asynchronous callbacks for displaying results. Private Shared Sub AddCallback(ByVal sender As Object, ByVal e As AddCompletedEventArgs) Console.WriteLine("Add Result: {0}", e.Result) End Sub
Sebelum memanggil operasi, gunakan generik System.EventHandler<TEventArgs> jenis <
operationName
>EventArgs
baru untuk menambahkan metode penghandel (dibuat pada langkah sebelumnya) ke peristiwa <operationName
>Completed
. Kemudian panggil metode <operationName
>Async
. Misalnya:// AddAsync double value1 = 100.00D; double value2 = 15.99D; client.AddCompleted += new EventHandler<AddCompletedEventArgs>(AddCallback); client.AddAsync(value1, value2); Console.WriteLine("Add({0},{1})", value1, value2);
' AddAsync Dim value1 As Double = 100 Dim value2 As Double = 15.99 AddHandler client.AddCompleted, AddressOf AddCallback client.AddAsync(value1, value2) Console.WriteLine("Add({0},{1})", value1, value2)
Contoh
Catatan
Panduan desain untuk status model asinkron berbasis peristiwa bahwa jika lebih dari satu nilai dikembalikan, satu nilai dikembalikan sebagai properti Result
dan yang lain dikembalikan sebagai properti pada objek EventArgs. Salah satu hasilnya adalah bahwa jika klien mengimpor metadata menggunakan opsi perintah asinkron berbasis peristiwa dan operasi mengembalikan lebih dari satu nilai, objek EventArgs default mengembalikan satu nilai sebagai properti Result
dan sisanya adalah properti objek EventArgs. Jika Anda ingin menerima objek pesan sebagai properti Result
dan memiliki nilai yang dikembalikan sebagai properti pada objek tersebut, gunakan opsi perintah /messageContract
. Ini menghasilkan tanda tangan yang mengembalikan pesan respons sebagai properti Result
pada objek EventArgs. Semua nilai pengembalian internal kemudian merupakan properti dari objek pesan respons.
using System;
namespace Microsoft.ServiceModel.Samples
{
// The service contract is defined in generatedClient.cs, generated from the service by the svcutil tool.
class Client
{
static void Main()
{
Console.WriteLine("Press <ENTER> to terminate client once the output is displayed.");
Console.WriteLine();
// Create a client
CalculatorClient client = new CalculatorClient();
// AddAsync
double value1 = 100.00D;
double value2 = 15.99D;
client.AddCompleted += new EventHandler<AddCompletedEventArgs>(AddCallback);
client.AddAsync(value1, value2);
Console.WriteLine("Add({0},{1})", value1, value2);
// SubtractAsync
value1 = 145.00D;
value2 = 76.54D;
client.SubtractCompleted += new EventHandler<SubtractCompletedEventArgs>(SubtractCallback);
client.SubtractAsync(value1, value2);
Console.WriteLine("Subtract({0},{1})", value1, value2);
// Multiply
value1 = 9.00D;
value2 = 81.25D;
double result = client.Multiply(value1, value2);
Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);
// Divide
value1 = 22.00D;
value2 = 7.00D;
result = client.Divide(value1, value2);
Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
Console.ReadLine();
//Closing the client gracefully closes the connection and cleans up resources
client.Close();
}
// Asynchronous callbacks for displaying results.
static void AddCallback(object sender, AddCompletedEventArgs e)
{
Console.WriteLine("Add Result: {0}", e.Result);
}
static void SubtractCallback(object sender, SubtractCompletedEventArgs e)
{
Console.WriteLine("Subtract Result: {0}", e.Result);
}
}
}
Namespace Microsoft.ServiceModel.Samples
' The service contract is defined in generatedClient.vb, generated from the service by the svcutil tool.
Class Client
Public Shared Sub Main()
Console.WriteLine("Press <ENTER> to terminate client once the output is displayed.")
Console.WriteLine()
' Create a client
Dim client As New CalculatorClient()
' AddAsync
Dim value1 As Double = 100
Dim value2 As Double = 15.99
AddHandler client.AddCompleted, AddressOf AddCallback
client.AddAsync(value1, value2)
Console.WriteLine("Add({0},{1})", value1, value2)
' SubtractAsync
value1 = 145
value2 = 76.54
AddHandler client.SubtractCompleted, AddressOf SubtractCallback
client.SubtractAsync(value1, value2)
Console.WriteLine("Subtract({0},{1})", value1, value2)
' Multiply
value1 = 9
value2 = 81.25
Dim result As Double = client.Multiply(value1, value2)
Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result)
' Divide
value1 = 22
value2 = 7
result = client.Divide(value1, value2)
Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result)
Console.ReadLine()
'Closing the client gracefully closes the connection and cleans up resources
client.Close()
End Sub
' Asynchronous callbacks for displaying results.
Private Shared Sub AddCallback(ByVal sender As Object, ByVal e As AddCompletedEventArgs)
Console.WriteLine("Add Result: {0}", e.Result)
End Sub
Private Shared Sub SubtractCallback(ByVal sender As Object, ByVal e As SubtractCompletedEventArgs)
Console.WriteLine("Subtract Result: {0}", e.Result)
End Sub
End Class
End Namespace