Asynchrone API's aanroepen in C# of Visual Basic

Windows bevat veel asynchrone API's om ervoor te zorgen dat uw app responsief blijft wanneer deze werkt, wat langere tijd kan duren. In dit onderwerp wordt beschreven hoe u asynchrone methoden gebruikt in C# of Microsoft Visual Basic.

Asynchrone API's zorgen ervoor dat uw app niet hoeft te wachten tot grote bewerkingen zijn voltooid voordat u doorgaat met de uitvoering. Een app die bijvoorbeeld informatie van internet downloadt, kan enkele seconden duren voordat de gegevens binnenkomen. Als u een synchrone methode gebruikt om de gegevens op te halen, wordt de app geblokkeerd totdat de methode wordt geretourneerd. De app reageert niet op gebruikersinteractie en omdat deze niet reageert, kan de gebruiker gefrustreerd raken. Door asynchrone API's te bieden, helpt Windows ervoor te zorgen dat uw app reageert op de gebruiker wanneer deze lange bewerkingen uitvoert.

De meeste asynchrone API's in Windows geen synchrone tegenhangers hebben, dus u moet weten hoe u de asynchrone API's gebruikt met C# of Visual Basic in uw Windows-app. Hier laten we zien hoe u asynchrone API's aanroept.

Asynchrone API's gebruiken

Volgens de conventie krijgen asynchrone methoden namen die eindigen op 'Async'. Doorgaans roept u asynchrone API's aan als reactie op de actie van een gebruiker, bijvoorbeeld wanneer de gebruiker op een knop klikt. Het aanroepen van een asynchrone methode in een gebeurtenishandler is een van de eenvoudigste manieren om asynchrone API's te gebruiken. Hier gebruiken we de wachtoperator als voorbeeld.

Stel dat u een app hebt met de titels van blogberichten vanaf een bepaalde locatie. De app heeft een knop waarop de gebruiker klikt om de titels op te halen. De titels worden weergegeven in een TextBlock. Wanneer de gebruiker op de knop klikt, is het belangrijk dat de app responsief blijft terwijl deze wacht op de informatie van de website van de blog. Om deze reactiesnelheid te garanderen, biedt Windows een asynchrone methode, SyndicationClient.RetrieveFeedAsync, om de feed te downloaden.

In het voorbeeld worden de lijsten met blogberichten van een blog opgehaald door de asynchrone methode SyndicationClient.RetrieveFeedAsync aan te roepen en het resultaat te wachten.

// Put the keyword async on the declaration of the event handler.
private async void Button_Click_1(object sender, RoutedEventArgs e)
{

    Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();

    Uri feedUri
        = new Uri("http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx");

    try
    {
        SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri);

        // The rest of this method executes after await RetrieveFeedAsync completes.
        rssOutput.Text = feed.Title.Text + Environment.NewLine;

        foreach (SyndicationItem item in feed.Items)
        {
            rssOutput.Text += item.Title.Text + ", " +
                             item.PublishedDate.ToString() + Environment.NewLine;
        }
    }
    catch (Exception ex)
    {
        // Log Error.
        rssOutput.Text =
            "I'm sorry, but I couldn't load the page," +
            " possibly due to network problems." +
            "Here's the error message I received: "
            + ex.ToString();
    }
}
' Put the keyword Async on the declaration of the event handler.
Private Async Sub Button_Click_1(sender As Object, e As RoutedEventArgs)
    Dim client As New Windows.Web.Syndication.SyndicationClient()
    Dim feedUri As New Uri("http://windowsteamblog.com/windows/b/windowsexperience/atom.aspx")

    Try
        Dim feed As SyndicationFeed = Await client.RetrieveFeedAsync(feedUri)

        ' The rest of this method executes after the await operation completes.
        rssOutput.Text = feed.Title.Text & vbCrLf

        For Each item In feed.Items
            rssOutput.Text += $"{item.Title.Text}, {item.PublishedDate.ToString()}{vbCrLf}"
        Next

    Catch ex As Exception
        ' Log Error.
        rssOutput.Text = "I'm sorry, but I couldn't load the page," &
                         " possibly due to network problems." &
                         "Here's the error message I received: " &
                          ex.ToString()
    End Try

End Sub

Er zijn enkele belangrijke dingen over dit voorbeeld. Eerst gebruikt de regel SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri) de wachtoperator met de aanroep naar de asynchrone methode RetrieveFeedAsync. U kunt de await-operator beschouwen alsof u de compiler vertelt dat u een asynchrone methode aanroept, waardoor de compiler wat extra werk verricht zodat u dat niet hoeft te doen. Vervolgens bevat de declaratie van de gebeurtenis-handler het asynchrone trefwoord. U moet dit trefwoord opnemen in de methodedeclaratie van een methode waarin u de wachtoperator gebruikt .

In dit onderwerp gaan we niet veel meer in op de details van wat de compiler doet met de wachtoperator , maar laten we eens kijken wat uw app doet, zodat deze asynchroon en responsief is. Bedenk wat er gebeurt wanneer u synchrone code gebruikt. Stel bijvoorbeeld dat er een methode is met de naam SyndicationClient.RetrieveFeed die synchroon is. (Er is geen dergelijke methode, maar stel dat er sprake is.) Als uw app de regel SyndicationFeed feed = client.RetrieveFeed(feedUri)bevat, in plaats van SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri), wordt de uitvoering van de app gestopt totdat de retourwaarde RetrieveFeed beschikbaar is. En terwijl uw app wacht tot de methode is voltooid, kan deze niet reageren op andere gebeurtenissen, zoals een andere Klik-gebeurtenis . Dat wil zeggen, uw app zou worden geblokkeerd totdat RetrieveFeed terugkeert.

Maar als u aanroept client.RetrieveFeedAsync, initieert de methode het ophalen en retourneert deze onmiddellijk. Wanneer u await gebruikt met RetrieveFeedAsync, verlaat de app de eventhandler tijdelijk. Vervolgens kunnen andere gebeurtenissen worden verwerkt terwijl RetrieveFeedAsync asynchroon wordt uitgevoerd. Hierdoor blijft de app responsief voor de gebruiker. Wanneer RetrieveFeedAsync is voltooid en de SyndicationFeed beschikbaar is, voert de app de gebeurtenis-handler opnieuw in waar deze is gebleven, na SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri), en voltooit de rest van de methode.

Het mooie van het gebruik van de wachtoperator is dat de code er niet veel anders uitziet dan hoe de code eruitziet als u de imaginaire RetrieveFeed methode hebt gebruikt. Er zijn manieren om asynchrone code te schrijven in C# of Visual Basic zonder de wachtoperator, maar de resulterende code benadrukt meestal de mechanica van het uitvoeren van asynchroon. Dit maakt asynchrone code moeilijk te schrijven, moeilijk te begrijpen en moeilijk te onderhouden. Met behulp van de await-operator krijgt u de voordelen van een asynchrone app zonder uw code complex te maken.

Retourtypen en resultaten van asynchrone API's

Als u de koppeling naar RetrieveFeedAsync hebt gevolgd, hebt u mogelijk gemerkt dat het retourtype RetrieveFeedAsync geen SyndicationFeed is. In plaats daarvan is het retourtype IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress>. Een asynchrone API die wordt weergegeven op basis van de onbewerkte syntaxis, retourneert een object dat het resultaat erin bevat. Hoewel het gebruikelijk en soms nuttig is om een asynchrone methode te beschouwen als wachtbaar, werkt de wachtoperator daadwerkelijk op de retourwaarde van de methode, niet op de methode. Wanneer u de wachtoperator toepast, krijgt u het resultaat van het aanroepen van GetResult op het object dat door de methode wordt geretourneerd. In het voorbeeld is de SyndicationFeed het resultaat van RetrieveFeedAsync.GetResult().

Wanneer u een asynchrone methode gebruikt, kunt u de handtekening onderzoeken om te zien wat u terugkrijgt nadat u hebt gewacht op de waarde die is geretourneerd door de methode. Alle asynchrone API's retourneren een van de volgende typen:

Het resultaattype van een asynchrone methode is hetzelfde als de TResult typeparameter. Typen zonder een TResult hebben geen resultaat. U kunt het resultaat beschouwen als een ongeldige waarde. In Visual Basic is een subprocedure gelijk aan een methode met een ongeldig retourtype.

De tabel hier bevat voorbeelden van asynchrone methoden en geeft een overzicht van het retourtype en het resultaattype van elke methode.

Asynchrone methode Terugbrengtype Resultaattype
SyndicationClient.RetrieveFeedAsync IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress> SyndicationFeed
FileOpenPicker.PickSingleFileAsync IAsyncOperation<StorageFile> Opslagbestand
XmlDocument.SaveToFileAsync IAsyncAction void
InkStrokeContainer.LoadAsync IAsyncActionWithProgress<UInt64> void
DataReader.LoadAsync DataReaderLoadOperation, een aangepaste resultatenklasse die IAsyncOperation<UInt32> implementeert UInt32

Note

FileOpenPicker en andere selectie-API's vereisen initialisatie met een vensterhandgreep (HWND) in WinUI 3-desktop-apps. Voordat u PickSingleFileAsync aanroept, roept u WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd) aan, waarbij hwnd afkomstig is van WindowNative.GetWindowHandle(this). Zie Display WinUI 3 picker-API's waarvoor een venstergreep (HWND) is vereist.

Asynchrone methoden die zijn gedefinieerd in .NET voor Windows-apps hebben het retourtype Task of Task<TResult>. Methoden die taak retourneren, zijn vergelijkbaar met de asynchrone methoden die IAsyncAction retourneren. In elk geval is het resultaat van de asynchrone methode ongeldig. Het retourtype Taak<TResult is vergelijkbaar met IAsyncOperation TResult><omdat het resultaat van de asynchrone methode bij het uitvoeren van de taak hetzelfde type is als de typeparameter.>TResult

Afhandeling van fouten

Wanneer u de wachtoperator gebruikt om uw resultaten op te halen uit een asynchrone methode, kunt u een try/catch-blok gebruiken om fouten op te lossen die optreden in asynchrone methoden, net zoals bij synchrone methoden. In het vorige voorbeeld worden de methode RetrieveFeedAsync en de bewerking await in een try/catch-blok geplaatst om fouten af te handelen wanneer er een uitzondering wordt gegenereerd.

Wanneer asynchrone methoden andere asynchrone methoden aanroepen, worden asynchrone methoden die tot een uitzondering leidt, doorgegeven aan de buitenste methoden. Dit betekent dat u een try/catch-blok rond de buitenste methode kunt plaatsen om fouten in de geneste asynchrone methoden op te vangen. Nogmaals, dit is vergelijkbaar met hoe u uitzonderingen voor synchrone methoden ondervangt. U kunt echter niet wachten in het catch-blok gebruiken.

Tip

Vanaf C# 6.0 (.NET Framework 4.6/Visual Studio 2015), kunt u wachten in het catch-blok gebruiken.

Samenvatting en volgende stappen

Het patroon van het aanroepen van een asynchrone methode die hier wordt weergegeven, is het eenvoudigst om te gebruiken wanneer u asynchrone API's aanroept in een gebeurtenis-handler. U kunt dit patroon ook gebruiken wanneer u een asynchrone methode aanroept in een overschreven methode die void of een Sub in Visual Basic retourneert.

Wanneer u asynchrone methoden tegenkomt, is het belangrijk om het volgende te onthouden:

  • Volgens de conventie krijgen asynchrone methoden namen die eindigen op 'Async'.
  • Elke methode die gebruikmaakt van de await-operator moet de declaratie hebben gemarkeerd met het asynchrone trefwoord.
  • Wanneer een app de wachtoperator vindt, blijft de app responsief op gebruikersinteractie terwijl de asynchrone methode wordt uitgevoerd.
  • Als u wacht op de waarde die wordt geretourneerd door een asynchrone methode, wordt een object geretourneerd dat het resultaat bevat. In de meeste gevallen is het resultaat in de retourwaarde nuttig, niet de retourwaarde zelf. U kunt het type van de waarde in het resultaat vinden door te kijken naar het retourtype van de asynchrone methode.
  • Het gebruik van asynchrone API's en asynchrone patronen is vaak een manier om de reactiesnelheid van uw app te verbeteren.

In het voorbeeld in dit onderwerp wordt tekst uitgevoerd die er als volgt uitziet.

Windows Experience Blog
PC Snapshot: Sony VAIO Y, 8/9/2011 10:26:56 AM -07:00
Tech Tuesday Live Twitter #Chat: Too Much Tech #win7tech, 8/8/2011 12:48:26 PM -07:00
Windows 7 themes: what's new and what's popular!, 8/4/2011 11:56:28 AM -07:00
PC Snapshot: Toshiba Satellite A665 3D, 8/2/2011 8:59:15 AM -07:00
Time for new school supplies? Find back-to-school deals on Windows 7 PCs and Office 2010, 8/1/2011 2:14:40 PM -07:00
Best PCs for blogging (or working) on the go, 8/1/2011 10:08:14 AM -07:00
Tech Tuesday – Blogging Tips and Tricks–#win7tech, 8/1/2011 9:35:54 AM -07:00
PC Snapshot: Lenovo IdeaPad U460, 7/29/2011 9:23:05 AM -07:00
GIVEAWAY: Survive BlogHer with a Sony VAIO SA and a Samsung Focus, 7/28/2011 7:27:14 AM -07:00
3 Ways to Stay Cool This Summer, 7/26/2011 4:58:23 PM -07:00
Getting RAW support in Photo Gallery & Windows 7 (…and a contest!), 7/26/2011 10:40:51 AM -07:00
Tech Tuesdays Live Twitter Chats: Photography Tips, Tricks and Essentials, 7/25/2011 12:33:06 PM -07:00
3 Tips to Go Green With Your PC, 7/22/2011 9:19:43 AM -07:00
How to: Buy a Green PC, 7/22/2011 9:13:22 AM -07:00
Windows 7 themes: the distinctive artwork of Cheng Ling, 7/20/2011 9:53:07 AM -07:00