Volání asynchronních rozhraní API v jazyce C# nebo Visual Basic

Windows obsahuje mnoho asynchronních rozhraní API, aby aplikace zůstala responzivní, když funguje, a to může trvat delší dobu. Toto téma popisuje, jak používat asynchronní metody v jazyce C# nebo Microsoft Visual Basic.

Asynchronní rozhraní API zabraňují tomu, aby vaše aplikace čekala na dokončení rozsáhlých operací, než bude pokračovat v provádění. Například aplikace, která stahuje informace z internetu, může strávit několik sekund čekáním na doručení informací. Pokud k načtení informací použijete synchronní metodu, aplikace se zablokuje, dokud metoda nevrátí. Aplikace nereaguje na interakci uživatelů a protože se zdá, že nereaguje, může být uživatel frustrovaný. Poskytnutím asynchronních rozhraní API Windows pomáhá zajistit, aby vaše aplikace zůstala reagovat na uživatele při provádění dlouhých operací.

Většina asynchronních rozhraní API v Windows nemá synchronní protějšky, takže musíte vědět, jak používat asynchronní rozhraní API s jazykem C# nebo Visual Basic v aplikaci Windows. Zde si ukážeme, jak volat asynchronní API.

Použití asynchronních rozhraní API

Podle konvence mají asynchronní metody názvy, které končí na "Async". Asynchronní rozhraní API obvykle voláte v reakci na akci uživatele, například když uživatel klikne na tlačítko. Volání asynchronní metody v obslužné rutině události je jedním z nejjednodušších způsobů použití asynchronních rozhraní API. Tady jako příklad použijeme operátor await .

Předpokládejme, že máte aplikaci, která uvádí názvy blogových příspěvků z určitého umístění. Aplikace má tlačítko , na které uživatel klikne, aby získal názvy. Názvy se zobrazí v bloku Textu. Když uživatel klikne na tlačítko, je důležité, aby aplikace zůstala responzivní, zatímco čeká na informace z webu blogu. Pro zajištění této odezvy poskytuje Windows asynchronní metodu SyndicationClient.RetrieveFeedAsync ke stažení informačního kanálu.

Tento příklad získá seznamy blogových příspěvků z blogu voláním asynchronní metody , SyndicationClient.RetrieveFeedAsync a čeká na výsledek.

// 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

V tomto příkladu je několik důležitých věcí. Nejprve řádek SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri) používá operátor await s voláním asynchronní metody RetrieveFeedAsync. Operátor await si můžete představit tak, že kompilátoru říkáte, že voláte asynchronní metodu, což způsobí, že kompilátor provede nějakou další práci, takže nemusíte. Dále deklarace obslužné metody události obsahuje klíčové slovo async. Toto klíčové slovo musíte zahrnout do deklarace metody jakékoli metody, ve které používáte operátor await .

V tomto tématu se nebudeme zabývat mnoha podrobnostmi o tom, co kompilátor dělá s operátorem await , ale pojďme se podívat, co vaše aplikace dělá, aby byla asynchronní a responzivní. Zvažte, co se stane, když použijete synchronní kód. Předpokládejme například, že existuje metoda, která je synchronní SyndicationClient.RetrieveFeed . (Neexistuje žádná taková metoda, ale představte si, že existuje.) Pokud by aplikace obsahovala řádek SyndicationFeed feed = client.RetrieveFeed(feedUri)místo SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri)spuštění aplikace, zastaví se, dokud nebude k dispozici vrácená RetrieveFeed hodnota. Zatímco vaše aplikace čeká na dokončení metody, nemůže reagovat na žádné jiné události, například na jinou událost Click . To znamená, že vaše aplikace by byla blokovaná, dokud RetrieveFeed se nevrátí.

Pokud však zavoláte client.RetrieveFeedAsync, metoda zahájí načítání a okamžitě vrátí. Když použijete await s RetrieveFeedAsync, aplikace dočasně ukončí obslužnou rutinu události. Pak může zpracovávat další události, zatímco RetrieveFeedAsync se spouští asynchronně. Aplikace tak bude reagovat na uživatele. Po dokončení funkce RetrieveFeedAsync a je k dispozici SyndicationFeed , aplikace v podstatě znovu zadá obslužnou rutinu události, kde skončila, po SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri)a dokončí zbytek metody.

Na používání operátoru await je skvělé to, že kód nevypadá o moc jinak než tehdy, kdybyste použili fiktivní metodu RetrieveFeed. Existují způsoby psaní asynchronního kódu v jazyce C# nebo Visual Basic bez operátoru await, ale výsledný kód má tendenci zdůraznit mechaniku provádění asynchronně. To znesnadňuje psaní asynchronního kódu, obtížně pochopitelné a obtížně udržovatelné. Pomocí operátoru await získáte výhody asynchronní aplikace bez složitého kódu.

Vrácení typů a výsledků asynchronních rozhraní API

Pokud jste postupovali podle odkazu na RetrieveFeedAsync, možná jste si všimli, že návratový typ RetrieveFeedAsync není SyndicationFeedFeed. Místo toho je návratový typ IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress>. V zobrazení z nezpracované syntaxe vrátí asynchronní rozhraní API objekt, který obsahuje výsledek v rámci této syntaxe. I když je běžné a někdy užitečné si představit asynchronní metodu jako očekávanou, operátor await ve skutečnosti pracuje s návratovou hodnotou metody, nikoli s metodou. Když použijete operátor await , co získáte zpět je výsledek volání GetResult na objekt vrácený metodou. V příkladu je SyndicationFeed výsledkem RetrieveFeedAsync.GetResult().

Když použijete asynchronní metodu, můžete se podívat na její signaturu a zjistit, jaký výsledek získáte po awaitování návratové hodnoty metody. Všechna asynchronní rozhraní API vrací jeden z následujících typů:

Typ výsledku asynchronní metody je stejný jako TResult parametr typu. Typy bez TResult nemají výsledek. Výsledek si můžete představit jako neplatný. V Visual Basic je procedura Sub ekvivalentní metodě s návratovým typem void.

Tabulka obsahuje příklady asynchronních metod a uvádí návratový typ a typ výsledku každého z nich.

Asynchronní metoda Návratový typ Typ výsledku
SyndicationClient.RetrieveFeedAsync IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress> SyndicationFeed
FileOpenPicker.PickSingleFileAsync IAsyncOperation<StorageFile> ÚložnýSoubor
XmlDocument.SaveToFileAsync IAsyncAction prázdnota
InkStrokeContainer.LoadAsync IAsyncActionWithProgress<UInt64> prázdnota
DataReader.LoadAsync DataReaderLoadOperation, vlastní třída výsledků, která implementuje IAsyncOperation<UInt32> Uint32

Note

FileOpenPicker a další rozhraní API pro výběr vyžadují inicializaci popisovače oken (HWND) v desktopových aplikacích WinUI 3. Před voláním PickSingleFileAsync zavolejte WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd), přičemž hwnd pochází z WindowNative.GetWindowHandle(this). Viz Rozhraní API pro výběr zobrazení WinUI 3, která vyžadují úchyt okna (HWND).

Asynchronní metody definované v .NET pro Windows aplikace mají návratový typ Task nebo Task<TResult>. Metody vracející úlohu jsou podobné asynchronním metodám, které vracejí IAsyncAction. V každém případě je výsledek asynchronní metody void. Návratový typ Task<TResult> je podobný IAsyncOperation<TResult> v tom, že výsledek asynchronní metody při spuštění úlohy je stejný typ jako TResult parametr typu.

Zpracování chyb

Pokud k načtení výsledků z asynchronní metody použijete operátor await , můžete použít blok try/catch ke zpracování chyb, ke kterým dochází v asynchronních metodách, stejně jako u synchronních metod. Předchozí příklad zabalí metodu RetrieveFeedAsync a operaci await v bloku try/catch , aby zpracovávala chyby při vyvolání výjimky.

Když asynchronní metody volají jiné asynchronní metody, všechny asynchronní metody, které mají za následek výjimku, se rozšíří do vnějších metod. To znamená, že můžete do nejvzdálenější metody vložit blok try/catch pro zachytávání chyb z vnořených asynchronních metod. Opět je to podobné tomu, jak zachytáváte výjimky pro synchronní metody. V bloku catch však nemůžete použít příkaz Await.

Tip

Příkaz await můžete použít v blokech catch a finally (podporované od verze C# 6.0).

Shrnutí a další kroky

Vzor volání asynchronní metody, kterou zde ukážeme, je nejjednodušší použít při volání asynchronních rozhraní API v obslužné rutině události. Tento vzor můžete použít také při volání asynchronní metody v přepsáné metodě, která vrací void nebo Sub v Visual Basic.

Jak narazíte na asynchronní metody, je důležité si uvědomit:

  • Podle konvence mají asynchronní metody názvy, které končí na "Async".
  • Každá metoda, která používá operátor await , musí mít svou deklaraci označenou asynchronním klíčovým slovem.
  • Když aplikace najde operátor await , aplikace zůstane reagovat na interakci uživatele, zatímco asynchronní metoda se spustí.
  • Čekání na hodnotu vrácenou asynchronní metodou vrátí objekt, který obsahuje výsledek. Ve většině případů je výsledek obsažený v návratové hodnotě užitečný, nikoli samotná vrácená hodnota. Typ hodnoty, která je obsažena ve výsledku, můžete najít tak, že se podíváte na návratový typ asynchronní metody.
  • Použití asynchronních rozhraní API a asynchronních vzorů je často způsob, jak zlepšit rychlost odezvy aplikace.

Příklad v tomto tématu vypíše text, který vypadá takto.

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