Erstellen asynchroner XML-Webdienstmethoden
Um die Leistung von XML-Webdienstmethoden zu steigern, die zeitintensive und somit ihren Thread blockierende Methoden aufrufen, sollten Sie diese als asynchrone XML-Webdienstmethoden offen legen. Durch Implementieren einer asynchronen XML-Webdienstmethode kann der Thread anderen Code ausführen, wenn er an den Threadpool zurückgegeben wird. Auf diese Weise kann ein weiterer Thread aus der begrenzten Anzahl im Treadpool ausgeführt und so die allgemeine Leistung und Skalierbarkeit des Systems gesteigert werden.
Grundsätzlich sind solche XML-Webdienstmethoden besonders gut für die asynchrone Implementierung geeignet, die Methoden aufrufen, die E/A-Vorgänge ausführen. Beispiele für solche Methoden sind Methoden, die mit anderen XML-Webdiensten kommunizieren, auf Remotedatenbanken zugreifen, Netzwerk-E/A ausführen und in große Dateien schreiben. Diese Methoden beanspruchen bei der Ausführung in der Hardware viel Zeit, so dass der Thread blockiert wird, der die XML-Webdienstmethode ausführt. Dieser Thread kann zum Ausführen von anderem Code freigegeben werden, wenn die XML-Webdienstmethode asynchron implementiert wird.
Unabhängig von der asynchronen Implementierung einer XML-Webdienstmethode können die Clients asynchron mit dieser kommunizieren. Asynchrone Kommunikation wird gegenüber .NET-Clients in der vom Web Services Description Language-Tool (WSDL.EXE) erstellten Proxyklasse offen gelegt, auch wenn eine XML-Webdienstmethode synchron implementiert wird. Die Proxyklasse enthält die Methoden Begin und End für die asynchrone Kommunikation mit allen XML-Webdienstmethoden. Die Entscheidung über die asynchrone oder synchrone Implementierung einer XML-Webdienstmethode sollte daher auf der Leistung basieren.
Hinweis Die Implementierung einer asynchronen XML-Webdienstmethode hat keinen Einfluss auf die HTTP-Verbindung zwischen dem Client und dem Server, der den Host für den XML-Webdienst darstellt. Die HTTP-Verbindung wird weder getrennt noch in einen Pool aufgenommen.
So implementieren Sie eine asynchrone XML-Webdienstmethode
Die Implementierung einer asynchronen XML-Webdienstmethode basiert auf dem asynchronen .NET Framework-Entwurfsmuster.
Teilen Sie eine synchrone XML-Webdienstmethode in zwei Methoden auf. Beide haben denselben Basisnamen, der eine beginnt jedoch mit Begin und der andere mit End.
Die Parameterliste für die Begin-Methode enthält alle in-Parameter und alle by reference-Parameter für die Funktionalität der Methode sowie zwei am Ende eingefügte Parameter.
- By reference-Parameter werden als in-Parameter aufgelistet.
- Bei dem vorletzten Parameter muss es sich um einen AsyncCallback handeln. Mit dem AsyncCallback-Parameter kann ein Client einen Delegaten bereitstellen, der beim Abschluss der Methode aufgerufen wird. Wenn eine asynchrone XML-Webdienstmethode eine andere asynchrone Methode aufruft, kann dieser Parameter an den vorletzten Parameter für diese Methode übergeben werden.
- Der letzte Parameter ist ein Object. Mit dem Object-Parameter kann ein Aufrufer Zustandsinformationen für die Methode bereitstellen. Wenn eine asynchrone XML-Webdienstmethode eine andere asynchrone Methode aufruft, kann dieser Parameter an den letzten Parameter für diese Methode übergeben werden.
- Der Rückgabewert muss vom Typ IAsyncResult sein.
Im folgenden Codebeispiel wird eine Begin-Methode dargestellt, die über einen für die Funktionalität der Methode spezifischen String-Parameter verfügt.
[WebMethod] public IAsyncResult BeginGetAuthorRoyalties(String Author, AsyncCallback callback, object asyncState) [Visual Basic] <WebMethod()> _ Public Function BeginGetAuthorRoyalties(ByVal Author As String, _ ByVal callback As AsyncCallback, ByVal asyncState As Object) _ As IAsyncResult
Die Parameterliste für die End-Methode besteht aus einem IAsyncResult gefolgt von beliebigen out- und by reference-Parametern, die für die Funktionalität der Methode spezifisch sind.
- Der Rückgabewert ist von demselben Typ wie der Rückgabewert einer synchronen XML-Webdienstmethode.
- By reference-Parameter werden als out-Parameter aufgeführt.
Im folgenden Codebeispiel wird eine End-Methode dargestellt, die einen benutzerdefinierten
AuthorRoyalties
-Typ zurückgibt.[WebMethod] public AuthorRoyalties EndGetAuthorRoyalties(IAsyncResult asyncResult) [Visual Basic] <WebMethod()> _ Public Function EndGetAuthorRoyalties(ByVal asyncResult As _ IAsyncResult) As AuthorRoyalties
Im folgenden Codebeispiel wird eine asynchrone XML-Webdienstmethode dargestellt, die asynchron mit einer anderen XML-Webdienstmethode kommuniziert.
using System; using System.Web.Services; [WebService(Namespace="https://www.contoso.com/")] public class MyService : WebService { public RemoteService remoteService; public MyService() { // Create a new instance of proxy class for // the XML Web service to be called. remoteService = new RemoteService(); } // Define the Begin method. [WebMethod] public IAsyncResult BeginGetAuthorRoyalties(String Author, AsyncCallback callback, object asyncState) { // Begin asynchronous communictation with a different XML Web // service. return remoteService.BeginReturnedStronglyTypedDS(Author, callback,asyncState); } // Define the End method. [WebMethod] public AuthorRoyalties EndGetAuthorRoyalties(IAsyncResult asyncResult) { // Return the asynchronous result from the other XML Web service. return remoteService.EndReturnedStronglyTypedDS(asyncResult); } } [Visual Basic] Imports System.Web.Services <WebService(Namespace:="https://www.contoso.com/")> _ Public Class MyService Inherits WebService Public remoteService As RemoteService Public Sub New() MyBase.New() ' Create a new instance of proxy class for ' the XML Web service to be called. remoteService = New RemoteService() End Sub ' Define the Begin method. <WebMethod()> _ Public Function BeginGetAuthorRoyalties(ByVal Author As String, _ ByVal callback As AsyncCallback, ByVal asyncState As Object) _ As IAsyncResult ' Begin asynchronous communictation with a different XML Web ' service. Return remoteService.BeginReturnedStronglyTypedDS(Author, _ callback, asyncState) End Function ' Define the End method. <WebMethod()> _ Public Function EndGetAuthorRoyalties(ByVal asyncResult As _ IAsyncResult) As AuthorRoyalties ' Return the asynchronous result from the other XML Web service. Return remoteService.EndReturnedStronglyTypedDS(asyncResult) End Function End Class
Das folgende Codebeispiel veranschaulicht, wie asynchrone Aufrufen verkettet werden, wenn eine XML-Webdienstmethode mehr als einen asynchronen Aufruf durchführt und die Aufrufe sequenziell ausgeführt werden müssen. Die BeginGetAuthorRoyalties
-Methode führt einen asynchronen Aufruf durch, um die Gültigkeit des übergebenen Autors zu ermitteln, und richtet einen Zwischenrückruf mit dem Namen AuthorRoyaltiesCallback
zum Empfangen der Ergebnisse ein. In diesem Zwischenrückruf wird dann ein asynchroner Aufruf durchgeführt, um die Tantiemen (Royalties) für den Autor zu bestimmen, wenn dieser Autor gültig ist.
using System.Web.Services;
using System.Data;
using System;
// This imports the proxy class for the XML Web services
// that the sample communicates with.
using AsyncWS.localhost;
namespace AsyncWS
{
[WebService(Namespace="https://www.contoso.com/")]
public class MyService : System.Web.Services.WebService
{
public RemoteService remoteService;
public MyService()
{
remoteService = new RemoteService();
}
[WebMethod]
public IAsyncResult BeginGetAuthorRoyalties(String Author,
AsyncCallback callback, Object asyncState)
{
// Saves the current state for the call that gets the author's
// royalties.
AsyncStateChain state = new AsyncStateChain();
state.originalState = asyncState;
state.Author = Author;
state.originalCallback = callback;
// Creates an intermediary callback.
AsyncCallback chainedCallback = new
AsyncCallback(AuthorRoyaltiesCallback);
return remoteService.BeginGetAuthors(chainedCallback,state);
}
// Intermediate method to handle chaining the
// asynchronous calls.
public void AuthorRoyaltiesCallback(IAsyncResult ar)
{
AsyncStateChain state = (AsyncStateChain)ar.AsyncState;
RemoteService rs = new RemoteService();
// Gets the result from the call to GetAuthors.
Authors allAuthors = rs.EndGetAuthors(ar);
Boolean found = false;
// Verifies that the requested author is valid.
int i = 0;
DataRow row;
while (i < allAuthors.authors.Rows.Count && !found)
{
row = allAuthors.authors.Rows[i];
if (row["au_lname"].ToString() == state.Author)
{
found = true;
}
i++;
}
if (found)
{
AsyncCallback cb = state.originalCallback;
// Calls the second XML Web service, because the author is
// valid.
rs.BeginReturnedStronglyTypedDS(state.Author,cb,state);
}
else
{
// Cannot throw the exception in this function or the XML Web
// service will hang. So, set the state argument to the
// exception and let the End method of the chained XML Web
// service check for it.
ArgumentException ex = new ArgumentException(
"Author does not exist.","Author");
AsyncCallback cb = state.originalCallback;
// Call the second XML Web service, setting the state to an
// exception.
rs.BeginReturnedStronglyTypedDS(state.Author,cb,ex);
}
}
[WebMethod]
public AuthorRoyalties EndGetAuthorRoyalties(IAsyncResult
asyncResult)
{
// Check whehter the first XML Web service threw an exception.
if (asyncResult.AsyncState is ArgumentException)
throw (ArgumentException) asyncResult.AsyncState;
else
return remoteService.EndReturnedStronglyTypedDS(asyncResult);
}
}
// Class to wrap the callback and state for the intermediate
// asynchronous operation.
public class AsyncStateChain
{
public AsyncCallback originalCallback;
public Object originalState;
public String Author;
}
}
[Visual Basic]
Imports System.Web.Services
Imports System.Data
Imports System
' This imports the proxy class for the XML Web services
' that the sample communicates with.
Imports AsyncWS_VB.localhost
Namespace AsyncWs
<WebService(Namespace:="https://www.contoso.com/")> _
Public Class MyService
Inherits WebService
Public remoteService As remoteService
Public Sub New()
MyBase.New()
remoteService = New localhost.RemoteService()
End Sub
' Defines the Begin method.
<WebMethod()> _
Public Function BeginGetAuthorRoyalties(ByVal Author As String, _
ByVal callback As AsyncCallback, ByVal asyncState As Object) _
As IAsyncResult
' Saves the current state for the call that gets the author's
' royalties.
Dim state As AsyncStateChain = New AsyncStateChain()
state.originalState = asyncState
state.Author = Author
state.originalCallback = callback
' Creates an intermediary callback.
Dim chainedCallback As AsyncCallback = New AsyncCallback( _
AddressOf AuthorRoyaltiesCallback)
' Begin asynchronous communictation with a different XML Web
' service.
Return remoteService.BeginGetAuthors(chainedCallback, state)
End Function
' Intermediate method to handle chaining the asynchronous calls.
Public Sub AuthorRoyaltiesCallback(ByVal ar As IAsyncResult)
Dim state As AsyncStateChain = CType(ar.AsyncState, _
AsyncStateChain)
Dim rs As RemoteService = New RemoteService()
' Gets the result from the call to GetAuthors.
Dim allAuthors As Authors = rs.EndGetAuthors(ar)
Dim found As Boolean = False
' Verifies that the requested author is valid.
Dim i As Integer = 0
Dim row As DataRow
While (i < allAuthors.authors.Rows.Count And (Not found))
row = allAuthors.authors.Rows(i)
If (row("au_lname").ToString() = state.Author) Then
found = True
End If
i = i + 1
End While
If (found) Then
Dim cb As AsyncCallback = state.originalCallback
' Calls the second XML Web service, because the author is
' valid.
rs.BeginReturnedStronglyTypedDS(state.Author, cb, state)
Else
' Cannot throw the exception in this function or the XML Web
' service will hang. So, set the state argument to the
' exception and let the End method of the chained XML Web
' service check for it.
Dim ex As ArgumentException = New ArgumentException( _
"Author does not exist.", "Author")
Dim cb As AsyncCallback = state.originalCallback
' Call the second XML Web service, setting the state to an
' exception.
rs.BeginReturnedStronglyTypedDS(state.Author, cb, ex)
End If
End Sub
' Define the End method.
<WebMethod()> _
Public Function EndGetAuthorRoyalties(ByVal asyncResult As _
IAsyncResult) As localhost.AuthorRoyalties
' Return the asynchronous result from the other XML Web service.
Return remoteService.EndReturnedStronglyTypedDS(asyncResult)
End Function
End Class
' Class to wrap the callback and state for the intermediate asynchronous
' operation.
Public Class AsyncStateChain
Public originalCallback As AsyncCallback
Public originalState As Object
Public Author As String
End Class
End Namespace
Siehe auch
Asynchrones Kommunizieren mit XML-Webdiensten | Einschließen asynchroner Aufrufe | Erstellen von XML-Webdiensten mit ASP.NET