Delen via


Synchrone en asynchrone bewerkingen

In dit onderwerp wordt beschreven hoe u asynchrone servicebewerkingen implementeert en aanroept.

Veel toepassingen roepen asynchroon methoden aan omdat de toepassing nuttig werk kan blijven doen terwijl de methodeaanroep wordt uitgevoerd. WcF-services (Windows Communication Foundation) en -clients kunnen deelnemen aan asynchrone bewerkingsaanroepen op twee verschillende niveaus van de toepassing, die WCF-toepassingen nog meer flexibiliteit bieden om de doorvoer te maximaliseren die in balans is met interactiviteit.

Typen Asynchrone bewerkingen

Alle servicecontracten in WCF, ongeacht de parameterstypen en retourwaarden, gebruiken WCF-kenmerken om een bepaald patroon voor berichtuitwisseling tussen client en service op te geven. WCF stuurt binnenkomende en uitgaande berichten automatisch naar de juiste servicebewerking of actieve clientcode.

De client beschikt alleen over het servicecontract, dat het berichtuitwisselingspatroon voor een bepaalde bewerking aangeeft. Clients kunnen de ontwikkelaar elk programmeermodel aanbieden dat ze kiezen, zolang het onderliggende berichtuitwisselingspatroon wordt waargenomen. Ook kunnen services bewerkingen op elke manier implementeren, zolang het opgegeven berichtpatroon wordt waargenomen.

De onafhankelijkheid van het servicecontract van de service- of client-implementatie maakt de volgende vormen van asynchrone uitvoering in WCF-toepassingen mogelijk:

  • Clients kunnen aanvraag-/antwoordbewerkingen asynchroon aanroepen met behulp van een synchrone berichtuitwisseling.

  • Services kunnen een aanvraag-/antwoordbewerking asynchroon implementeren met behulp van een synchrone berichtuitwisseling.

  • Berichtenuitwisseling kan in één richting zijn, ongeacht de implementatie van de client of service.

Voorgestelde asynchrone scenario's

Gebruik een asynchrone benadering in een implementatie van een servicebewerking als de implementatie van de bewerkingsservice een blokkeringsaanroep doet, zoals I/O-werk. Wanneer u zich in een asynchrone bewerkingsdistributie bevindt, probeert u asynchrone bewerkingen en methoden aan te roepen om het asynchrone aanroeppad zo veel mogelijk uit te breiden. U kunt bijvoorbeeld een van binnenuit BeginOperationOne()aanroepenBeginOperationTwo().

  • Gebruik in de volgende gevallen een asynchrone benadering in een client of aanroepende toepassing:

  • Als u bewerkingen aanroept vanuit een toepassing in de middelste laag. (Zie voor meer informatie over dergelijke scenario's Clienttoepassingen in de middelste laag.)

  • Als u bewerkingen aanroept binnen een ASP.NET pagina, gebruikt u asynchrone pagina's.

  • Als u bewerkingen aanroept vanuit een toepassing die één thread heeft, zoals Windows Forms of Windows Presentation Foundation (WPF). Wanneer u het asynchrone aanroepende model op basis van gebeurtenissen gebruikt, wordt de resultaatgebeurtenis gegenereerd op de UI-thread, waardoor reactiesnelheid wordt toegevoegd aan de toepassing zonder dat u zelf meerdere threads hoeft te verwerken.

  • Als u over het algemeen een keuze hebt tussen een synchrone en asynchrone aanroep, kiest u de asynchrone aanroep.

Een Asynchrone servicebewerking implementeren

Asynchrone bewerkingen kunnen worden geïmplementeerd met behulp van een van de drie volgende methoden:

  1. Het asynchrone patroon op basis van taken

  2. Het asynchrone patroon op basis van gebeurtenissen

  3. Het asynchrone IAsyncResult-patroon

Asynchroon patroon op basis van taken

Het asynchrone patroon op basis van taken is de voorkeurswijze voor het implementeren van asynchrone bewerkingen, omdat dit het eenvoudigste en meest direct is. Als u deze methode wilt gebruiken, implementeert u de servicebewerking en geeft u een retourtype taak<T> op, waarbij T het type is dat wordt geretourneerd door de logische bewerking. Voorbeeld:

public class SampleService:ISampleService
{
   // ...
   public async Task<string> SampleMethodTaskAsync(string msg)
   {
      return Task<string>.Factory.StartNew(() =>
      {
         return msg;
      });
   }
   // ...
}

De bewerking SampleMethodTaskAsync retourneert een taaktekenreeks<> omdat de logische bewerking een tekenreeks retourneert. Zie Het asynchrone patroon op basis van taken voor meer informatie over het asynchrone patroon op basis van taken.

Waarschuwing

Wanneer u het asynchrone patroon op basis van taken gebruikt, kan een T:System.AggregateException worden gegenereerd als er een uitzondering optreedt tijdens het wachten op de voltooiing van de bewerking. Deze uitzondering kan optreden op de client of services

Asynchroon patroon op basis van gebeurtenissen

Een service die het Asynchrone patroon op basis van gebeurtenissen ondersteunt, heeft een of meer bewerkingen met de naam MethodNameAsync. Deze methoden kunnen synchrone versies spiegelen, die dezelfde bewerking uitvoeren op de huidige thread. De klasse heeft mogelijk ook een MethodNameCompleted-gebeurtenis en heeft mogelijk een MethodNameAsyncCancel-methode (of gewoon CancelAsync). Een client die de bewerking wil aanroepen, definieert een gebeurtenis-handler die moet worden aangeroepen wanneer de bewerking is voltooid,

In het volgende codefragment ziet u hoe u asynchrone bewerkingen declareert met behulp van het asynchrone patroon op basis van gebeurtenissen.

public class AsyncExample
{
    // Synchronous methods.
    public int Method1(string param);
    public void Method2(double param);

    // Asynchronous methods.
    public void Method1Async(string param);
    public void Method1Async(string param, object userState);
    public event Method1CompletedEventHandler Method1Completed;

    public void Method2Async(double param);
    public void Method2Async(double param, object userState);
    public event Method2CompletedEventHandler Method2Completed;

    public void CancelAsync(object userState);

    public bool IsBusy { get; }

    // Class implementation not shown.
}

Zie Het Asynchrone patroon op basis van gebeurtenissen voor meer informatie over het Asynchrone patroon op basis van gebeurtenissen.

IAsyncResult asynchroon patroon

Een servicebewerking kan op asynchrone wijze worden geïmplementeerd met behulp van het asynchrone programmeerpatroon van .NET Framework en het markeren van de <Begin> methode waarbij de AsyncPattern eigenschap is ingesteld op true. In dit geval wordt de asynchrone bewerking weergegeven in metagegevens in dezelfde vorm als een synchrone bewerking: deze wordt weergegeven als één bewerking met een aanvraagbericht en een gecorreleerd antwoordbericht. Clientprogrammeermodellen hebben vervolgens een keuze. Ze kunnen dit patroon vertegenwoordigen als een synchrone bewerking of als een asynchrone bewerking, zolang de service een aanvraag-antwoordberichtuitwisseling aanroept.

Over het algemeen moet u, met de asynchrone aard van de systemen, geen afhankelijkheid van de threads nemen. De meest betrouwbare manier om gegevens door te geven aan verschillende fasen van de verzending van bewerkingen is het gebruik van extensies.

Zie Voor een voorbeeld: Een Asynchrone servicebewerking implementeren.

Een contractbewerking X definiëren die asynchroon wordt uitgevoerd, ongeacht hoe deze wordt aangeroepen in de clienttoepassing:

  • Definieer twee methoden met behulp van het patroon BeginOperation en EndOperation.

  • De BeginOperation methode bevat in en ref parameters voor de bewerking en retourneert een IAsyncResult type.

  • De EndOperation methode bevat een IAsyncResult parameter en de out parameters ref en retourneert het retourtype voor bewerkingen.

Zie bijvoorbeeld de volgende 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

Als u een asynchrone bewerking wilt maken, zijn de volgende twee methoden:

[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

Notitie

Het OperationContractAttribute kenmerk wordt alleen toegepast op de BeginDoWork methode. Het resulterende contract heeft één WSDL-bewerking met de naam DoWork.

Asynchrone aanroepen aan de clientzijde

Een WCF-clienttoepassing kan gebruikmaken van drie asynchrone aanroepende modellen die eerder zijn beschreven

Wanneer u het op taken gebaseerde model gebruikt, roept u de bewerking aan met behulp van het trefwoord await, zoals wordt weergegeven in het volgende codefragment.

await simpleServiceClient.SampleMethodTaskAsync("hello, world");

Als u het asynchrone patroon op basis van gebeurtenissen gebruikt, hoeft u alleen een gebeurtenis-handler toe te voegen om een melding van het antwoord te ontvangen. De resulterende gebeurtenis wordt automatisch gegenereerd op de gebruikersinterfacethread. Als u deze methode wilt gebruiken, geeft u zowel de opdrachtopties /async als /tcv:Version35 op met het hulpprogramma servicemodelmetagegevens (Svcutil.exe), zoals in het volgende voorbeeld.

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

Wanneer dit gebeurt, genereert Svcutil.exe een WCF-clientklasse met de gebeurtenisinfrastructuur waarmee de aanroepende toepassing een gebeurtenis-handler kan implementeren en toewijzen om het antwoord te ontvangen en de juiste actie te ondernemen. Zie Procedure voor een volledig voorbeeld: Servicebewerkingen asynchroon aanroepen.

Het asynchrone model op basis van gebeurtenissen is echter alleen beschikbaar in .NET Framework 3.5. Bovendien wordt het niet ondersteund, zelfs niet in .NET Framework 3.5 wanneer een WCF-clientkanaal wordt gemaakt met behulp van een System.ServiceModel.ChannelFactory<TChannel>. Met WCF-clientkanaalobjecten moet u objecten gebruiken System.IAsyncResult om uw bewerkingen asynchroon aan te roepen. Als u deze methode wilt gebruiken, geeft u de opdrachtoptie /async op met het hulpprogramma servicemodelmetagegevens (Svcutil.exe), zoals in het volgende voorbeeld.

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

Hiermee wordt een servicecontract gegenereerd waarin elke bewerking wordt gemodelleerd als een <Begin> methode waarbij de AsyncPattern eigenschap is ingesteld true op en een bijbehorende <End> methode. Zie Procedure voor een volledig voorbeeld van een ChannelFactory<TChannel>aanroepbewerkingen asynchroon met behulp van een kanaalfactory.

In beide gevallen kunnen toepassingen een bewerking asynchroon aanroepen, zelfs als de service synchroon wordt geïmplementeerd, op dezelfde manier als een toepassing hetzelfde patroon kan gebruiken om asynchroon een lokale synchrone methode aan te roepen. Hoe de bewerking wordt geïmplementeerd, is niet van belang voor de client; wanneer het antwoordbericht binnenkomt, wordt de inhoud verzonden naar de asynchrone <End> methode van de client en haalt de client de informatie op.

Patronen voor het uitwisselen van berichten in één richting

U kunt ook een asynchroon berichtuitwisselingspatroon maken waarin bewerkingen (bewerkingen waarvoor het OperationContractAttribute.IsOneWay antwoord true niet is gecorreleerd) door de client of service onafhankelijk van de andere kant kunnen worden verzonden. (Dit maakt gebruik van het dubbelzijdige berichtuitwisselingspatroon met berichten in één richting.) In dit geval geeft het servicecontract een eenrichtingsberichtuitwisseling op die aan beide zijden kan worden geïmplementeerd als asynchrone aanroepen of implementaties, of niet, indien van toepassing. Wanneer het contract een uitwisseling is van berichten in één richting, kunnen de implementaties grotendeels asynchroon zijn, omdat zodra een bericht wordt verzonden, de toepassing niet op een antwoord wacht en ander werk kan blijven doen.

Asynchrone asynchrone clients en berichtcontracten op basis van gebeurtenissen

De ontwerprichtlijnen voor de asynchrone modelstatus op basis van gebeurtenissen dat als er meer dan één waarde wordt geretourneerd, één waarde wordt geretourneerd als de Result eigenschap en de andere als eigenschappen voor het EventArgs object worden geretourneerd. Een resultaat hiervan is dat als een client metagegevens importeert met behulp van de asynchrone opdrachtopties op basis van gebeurtenissen en de bewerking meer dan één waarde retourneert, retourneert het standaardobject EventArgs één waarde als de Result eigenschap en de rest zijn eigenschappen van het EventArgs object.

Als u het berichtobject wilt ontvangen als de Result eigenschap en de geretourneerde waarden als eigenschappen voor dat object wilt hebben, gebruikt u de opdrachtoptie /messageContract . Hiermee wordt een handtekening gegenereerd die het antwoordbericht retourneert als de Result eigenschap van het EventArgs object. Alle interne retourwaarden zijn vervolgens eigenschappen van het antwoordberichtobject.

Zie ook