Freigeben über


Synchrone und asynchrone Vorgänge

Beschreibt lokale asynchrone Implementierungen und Aufrufe sowie die synchrone Verwendung eines asynchronen Nachrichtenaustauschs.

Viele Anwendungen rufen Methoden asynchron auf, weil dadurch die Anwendung beim Methodenaufruf weiter nützliche Arbeiten ausführen kann. Windows Communication Foundation (WCF)-Dienste und Clients können an asynchronen Vorgangsaufrufen auf zwei unterschiedlichen Anwendungsebenen teilnehmen, was WCF-Anwendungen noch mehr Flexibilität zum Maximieren des Durchsatzes abgewogen gegen Interaktivität bietet.

Typen asynchroner Vorgänge

Alle Dienstverträge in WCF verwenden unabhängig von den Parametertypen und Rückgabewerten WCF-Attribute zum Angeben eines bestimmten SOAP-Nachrichtenaustauschmusters zwischen Client und Dienst. WCF leitet automatisch eingehende und ausgehende SOAP-Nachrichten an den entsprechenden Dienstvorgang oder ausführenden Clientcode weiter.

Der Client verfügt nur über den Dienstvertrag, der das Nachrichtenaustauschmuster für einen bestimmten Vorgang angibt. Clients können dem Entwickler ein beliebiges Programmiermodell anbieten, solange das zugrunde liegende Nachrichtenaustauschmuster eingehalten wird. Ebenso können Dienste Vorgänge auf beliebige Weise implementieren, solange das angegebene Nachrichtenmuster eingehalten wird.

Die Unabhängigkeit des Dienstvertrags von der Dienst- oder Clientimplementierung ermöglicht die folgenden Formen asynchroner Ausführung in WCF-Anwendungen:

  • Clients können Anforderungs-/Antwortvorgänge mit einem synchronen Nachrichtenaustausch asynchron aufrufen.
  • Clients können asynchrone Anforderungs-/Antwortvorgänge mit einem synchronen Nachrichtenaustausch implementieren.
  • Ein Nachrichtenaustausch kann unidirektional sein, unabhängig von der Implementierung des Clients oder Dienstes.

Vorgeschlagene asynchrone Szenarien

Verwenden Sie den asynchronen Ansatz in der Implementierung eines Dienstvorgangs, wenn dieser Dienstvorgang blockierende Aufrufe, beispielsweise E/A-Vorgänge vornimmt. Bei der Implementierung eines Dienstvorgangs sollten Sie versuchen, asynchrone Vorgänge und Methoden aufzurufen, um den asynchronen Aufrufpfad so weit wie möglich zu erweitern. Rufen Sie z. B. innerhalb von BeginOperationOne() BeginOperationTwo() auf.

  • Verwenden Sie in den folgenden Fällen einen asynchronen Ansatz in einem Client oder in einer aufrufenden Anwendung:
  • Wenn Sie Vorgänge von einer Anwendung der mittleren Ebene aufrufen. (Weitere Informationen zu solchen Szenarien finden Sie unter Clientanwendungen mittlerer Ebene.)
  • Verwenden Sie asynchrone Seiten, wenn Sie Vorgänge innerhalb einer ASP.NET-Seite aufrufen.
  • Wenn Sie Vorgänge von einer Singlethread-Anwendung aufrufen, etwa einer Windows Forms- oder Windows Presentation Foundation (WPF)-Anwendung. Bei Verwendung des ereignisgesteuerten asynchronen Aufrufmodells wird das resultierende Ereignis im UI-Thread ausgelöst. Dies erhöht die Ansprechempfindlichkeit der Anwendung gegenüber Benutzeraktivitäten, ohne dass Sie selbst mehrere Threads verwalten müssen.
  • Im Allgemeinen gilt: Haben Sie die Wahl zwischen einem synchronen oder einem asynchronen Aufruf, dann wählen Sie den asynchronen Aufruf.

Clientseitige asynchrone Aufrufe

Eine WCF-Clientanwendung kann eines von zwei asynchronen Aufrufmodellen verwenden, die beide in Asynchronous Programming Design Patterns beschrieben werden:

  • Asynchrone Vorgänge, die Ereignisse verwenden.
  • Asynchrone Vorgänge, die System.IAsyncResult-Objekte verwenden.

Der erste Ansatz, das ereignisbasierte asynchrone Muster, wird für aufrufende Anwendungen empfohlen, weil dabei nur ein Ereignishandler eingefügt werden muss, der die Benachrichtigung über die Antwort empfängt – und das Ereignis wird automatisch im Benutzeroberflächenthread ausgelöst. Geben Sie zum Verwenden dieses Ansatzes die /async- und die /tcv:Version35-Befehlsoption für das ServiceModel Metadata Utility Tool (Svcutil.exe) an, wie in folgendem Beispiel dargestellt:

svcutil https://localhost:8000/servicemodelsamples/service/mex /async /tcv:Version35

Dadurch generiert Svcutil.exe eine WCF-Clientklasse mit der Ereignisinfrastruktur, die es der aufrufenden Anwendung ermöglicht, einen Ereignishandler zu implementieren und zuzuweisen, der die Antwort empfängt und die entsprechende Aktion einleitet. Ein vollständiges Beispiel finden Sie unter Gewusst wie: Asynchrones Aufrufen von WCF-Dienstvorgängen.

Das ereignisbasierte asynchrone Modell ist jedoch nur in .NET Framework, Version 3.5 verfügbar. Es wird darüber hinaus nicht einmal in .NET Framework 3.5 unterstützt, wenn ein WCF-Clientkanal mithilfe einer System.ServiceModel.ChannelFactory erstellt wird. Bei WCF-Clientkanalobjekten müssen Sie System.IAsyncResult-Objekte verwenden, um die Vorgänge asynchron aufzurufen. Geben Sie zum Verwenden dieses Ansatzes die /async-Befehlsoption für das ServiceModel Metadata Utility Tool (Svcutil.exe) an, wie in folgendem Beispiel dargestellt:

svcutil https://localhost:8000/servicemodelsamples/service/mex /async 

Dadurch wird ein Dienstvertrag generiert, in dem jeder Vorgang als eine <Begin>-Methode mit der auf true festgelegten AsyncPattern-Eigenschaft und einer entsprechenden <End>-Methode modelliert wird. Ein vollständiges Beispiel, in dem eine ChannelFactory verwendet wird finden Sie unter Gewusst wie: Asynchrones Aufrufen von Vorgängen mit einer Kanalfactory.

In jedem Fall können Anwendungen einen Vorgang asynchron aufrufen, auch wenn der Dienst synchron implementiert wurde, ebenso wie eine Anwendung mit dem gleichen Muster eine lokale synchrone Methode asynchron aufrufen kann. Wie der Vorgang implementiert wird, ist für den Client nicht von Bedeutung; wenn die Antwortnachricht eintrifft, wird ihr Inhalt an die asynchrone <End>-Methode des Clients gesendet, und der Client ruft die Informationen ab.

Asynchrone Vorgangsimplementierungen

Entsprechend kann ein Dienstvorgang asynchron mit dem asynchronen .NET Framework-Programmierungsmuster implementiert werden, wobei die <Begin>-Methode mit der auf true festgelegten AsyncPattern-Eigenschaft markiert wird. In diesem Fall wird der asynchrone Vorgang in Metadaten in der gleichen Form wie ein synchroner Vorgang verfügbar gemacht: Er wird als einzelner Vorgang mit einer Anforderungsnachricht und einer korrelierten Antwortnachricht verfügbar gemacht. Clientprogrammierungsmodelle haben dann eine Wahl. Sie können dieses Muster als synchronen oder als asynchronen Vorgang darstellen, solange beim Aufrufen des Dienstes ein Anforderung-Antwort-Nachrichtenaustausch stattfindet.

Ein Beispiel finden Sie unter Gewusst wie: Implementieren eines asynchronen Dienstvorgangs.

So definieren Sie ein Vertragsvorgang-X, das unabhängig von der Art des Aufrufs in der Clientanwendung asynchron ausgeführt wird:

  • Definieren Sie zwei Methoden mit dem Muster BeginOperation und EndOperation.
  • Die BeginOperation-Methode enthält den in-Parameter und den out-Parameter für den Vorgang und gibt einen IAsyncResult-Typ zurück.
  • Die EndOperation-Methode enthält ebenfalls einen IAsyncResult-Parameter sowie den in-Parameter und den out-Parameter und gibt den Rückgabewert des Vorgangs zurück.

Betrachten Sie beispielsweise die folgende Methode:

int DoWork(string data, ref string inout, out string outonly)
Function DoWork(ByVal data As String, ByRef inout As String, _
out outonly As out) As Integer

Die beiden Methoden zum Erstellen eines asynchronen Vorgangs sind:

[OperationContract(AsyncPattern=true)]
IAsyncResult BeginDoWork(string data, 
                          ref string inout, 
                          AsyncCallback callback, 
                          object state);
int EndDoWork(ref string inout, out string outonly, IAsyncResult result);
<OperationContract(AsyncPattern := True)>  _
Function BeginDoWork(ByVal data As String, _
                 ByRef inout As String, _
                 ByVal callback As AsyncCallback, _
                 ByVal state As Object) _
As IAsyncResult 

Function EndDoWork(ByRef inout As String, _
        ByRef outonly As String, _
        ByVal result As IAsyncResult) _
As Integer

Tipp

Das OperationContractAttribute-Attribut wird nur auf die BeginDoWork-Methode angewendet. Der resultierende Vertrag verfügt über einen WSDL-Vorgang mit der Bezeichnung DoWork.

Unidirektionale Nachrichtenaustauschmuster

Sie können auch ein asynchrones Nachrichtenaustauschmuster erstellen, in dem unidirektionale Vorgänge (Vorgänge, bei denen das System.ServiceModel.OperationContractAttribute.IsOneWay true ist, verfügen über keine korrelierte Antwort) vom Client oder vom Dienst unabhängig von der anderen Seite in beide Richtungen gesendet werden können. (Dabei wird das Duplex-Nachrichtenaustauschmuster mit unidirektionalen Nachrichten verwendet.) In diesem Fall gibt der Dienstvertrag einen unidirektionalen Nachrichtenaustausch an, den eine der beiden Seiten ggf. als asynchrone Aufrufe oder Implementierungen oder nicht implementieren kann. Im Allgemeinen können die Implementierungen, wenn der Vertrag ein Austausch von unidirektionalen Nachrichten ist, hauptsächlich synchron sein, da die Anwendung nach dem Senden der Nachricht nicht auf eine Antwort wartet und andere Aktivitäten weiter ausführen kann.

Ereignisbasierte asynchrone Clients und Nachrichtenverträge

Die Entwurfsrichtlinien für das ereignisbasierte asynchrone Modell besagen, dass in den Fällen, in denen mehr als ein Wert zurückgegeben wird, ein Wert in der Result-Eigenschaft und die übrigen Werte in Eigenschaften des EventArgs-Objekts zurückgegeben werden sollen. Wenn ein Client Metadaten mithilfe der ereignisbasierten asynchronen Befehlsoptionen importiert, und der Vorgang mehr als einen Wert zurückgibt, dann gibt das EventArgs-Standardobjekt infolgedessen einen Wert in der Result-Eigenschaft zurück, während die übrigen Werte in Eigenschaften des EventArgs-Objekts zurückgegeben werden.

Wenn das Nachrichtenobjekt in der Result-Eigenschaft und die Rückgabewerte als Eigenschaften dieses Objekts übermittelt werden sollen, verwenden Sie die /messageContract-Befehlsoption. Dadurch wird eine Signatur generiert, bei der die Antwortnachricht in der Result-Eigenschaft des EventArgs-Objekts zurückgegeben wird. Alle internen Rückgabewerte sind dann Eigenschaften des Antwortnachrichtenobjekts.

Siehe auch

Referenz

IsOneWay
AsyncPattern