Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Windows zawiera wiele asynchronicznych interfejsów API, dzięki którym aplikacja zachowuje responsywność podczas wykonywania zadań, których wykonanie może potrwać dłużej. W tym temacie omówiono sposób używania metod asynchronicznych w języku C# lub Microsoft Visual Basic.
Asynchroniczne interfejsy API uniemożliwiają aplikacji oczekiwanie na ukończenie dużych operacji przed kontynuowaniem wykonywania. Na przykład aplikacja, która pobiera informacje z Internetu, może poświęcić kilka sekund na oczekiwanie na nadejście informacji. Jeśli używasz metody synchronicznej do pobierania informacji, aplikacja zostanie zablokowana do momentu powrotu metody. Aplikacja nie będzie reagować na interakcję z użytkownikiem i ponieważ wydaje się nie odpowiadać, użytkownik może stać się sfrustrowany. Zapewniając asynchroniczne interfejsy API, Windows pomaga zapewnić, że aplikacja będzie reagować na użytkownika podczas wykonywania długich operacji.
Większość asynchronicznych interfejsów API w usłudze Windows nie ma synchronicznych odpowiedników, dlatego należy pamiętać, jak używać asynchronicznych interfejsów API w języku C# lub Visual Basic w aplikacji Windows. W tym miejscu pokazano, jak wywoływać asynchroniczne interfejsy API.
Używanie asynchronicznych interfejsów API
Zgodnie z konwencją metody asynchroniczne otrzymują nazwy kończące się na "Async". Interfejsy API asynchroniczne są zwykle wywoływane w odpowiedzi na akcję użytkownika, na przykład gdy użytkownik kliknie przycisk. Wywoływanie metody asynchronicznej w procedurze obsługi zdarzeń jest jednym z najprostszych sposobów używania asynchronicznych interfejsów API. W tym miejscu użyjemy operatora await jako przykładu.
Załóżmy, że masz aplikację zawierającą tytuły wpisów w blogu z określonej lokalizacji. Aplikacja ma Button, który użytkownik klika, aby wyświetlić tytuły. Tytuły są wyświetlane w elemecie TextBlock. Gdy użytkownik kliknie przycisk, należy pamiętać, że aplikacja będzie reagować, czekając na informacje z witryny internetowej blogu. Aby zapewnić ten czas odpowiedzi, Windows udostępnia metodę asynchroniczną SyndicationClient.RetrieveFeedAsync w celu pobrania źródła danych.
W tym przykładzie przedstawiono pobieranie list wpisów w blogu przez wywołanie metody asynchronicznej SyndicationClient.RetrieveFeedAsync i oczekiwanie na wynik.
// 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
W tym przykładzie przedstawiono kilka ważnych kwestii. Najpierw wiersz SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri) używa operatora await z wywołaniem metody asynchronicznej RetrieveFeedAsync. Możesz myśleć o operatorie await , mówiąc kompilatorowi, że wywołujesz metodę asynchroniczną, co powoduje, że kompilator wykonuje jakąś dodatkową pracę, aby nie trzeba było tego robić. Następnie deklaracja programu obsługi zdarzeń zawiera asynchroniczne słowo kluczowe. To słowo kluczowe należy uwzględnić w deklaracji metody dowolnej metody, w której używasz operatora await .
W tym temacie nie przejdziemy do wielu szczegółów tego, co kompilator wykonuje z operatorem await , ale sprawdźmy, co robi twoja aplikacja, aby była asynchroniczna i elastyczna. Zastanów się, co się stanie, gdy używasz kodu synchronicznego. Załóżmy na przykład, że istnieje metoda o nazwie SyndicationClient.RetrieveFeed , która jest synchroniczna. (Nie ma takiej metody, ale wyobraź sobie, że istnieje). Jeśli aplikacja zawierała wiersz SyndicationFeed feed = client.RetrieveFeed(feedUri), a nie SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri), wykonanie aplikacji zostanie zatrzymane do momentu udostępnienia wartości zwracanej RetrieveFeed . A gdy aplikacja czeka na ukończenie metody, nie może ona reagować na inne zdarzenia, takie jak inne zdarzenie Click . Oznacza to, że aplikacja zostanie zablokowana do momentu RetrieveFeed powrotu.
Jeśli jednak wywołasz client.RetrieveFeedAsync, metoda inicjuje pobieranie i natychmiast zwraca. Gdy używasz funkcji await z funkcją RetrieveFeedAsync, aplikacja tymczasowo zamyka procedurę obsługi zdarzeń. Następnie może przetwarzać inne zdarzenia, gdy funkcja RetrieveFeedAsync jest wykonywana asynchronicznie. Dzięki temu aplikacja reaguje na użytkownika. Po zakończeniu funkcji RetrieveFeedAsync i udostępnieniu metody SyndicationFeed aplikacja zasadniczo ponownie wprowadza procedurę obsługi zdarzeń, w której została przerwana, po SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri)i kończy resztę metody.
Dobrą rzeczą w korzystaniu z operatora await jest to, że kod nie wygląda znacznie inaczej niż sposób, w jaki kod wygląda, jeśli użyto metody wyimaginowanej RetrieveFeed . Istnieją sposoby pisania kodu asynchronicznego w języku C# lub Visual Basic bez operatora await, ale wynikowy kod zwykle podkreśla mechanikę wykonywania asynchronicznego. Sprawia to, że kod asynchroniczny jest trudny do pisania, trudne do zrozumienia i trudne do utrzymania. Korzystając z operatora await , uzyskujesz korzyści z aplikacji asynchronicznej bez tworzenia złożonego kodu.
Zwracane typy i wyniki asynchronicznych interfejsów API
Jeśli klikniesz link do RetrieveFeedAsync, być może zauważysz, że typ zwracany przez RetrieveFeedAsync nie jest typu SyndicationFeed. Zamiast tego zwracany typ to IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress>. Patrząc od strony surowej składni, asynchroniczny interfejs API zwraca obiekt zawierający wynik. Chociaż często i czasami przydatne jest myślenie o metodzie asynchronicznej jako oczekiwanej, operator await rzeczywiście działa na wartości zwracanej metody, a nie na metodzie. Po zastosowaniu operatora await otrzymujesz wynik wywołania metody GetResult na obiekcie zwróconym przez tę metodę. W tym przykładzie parametr SyndicationFeed jest wynikiem polecenia RetrieveFeedAsync.GetResult().
Jeśli używasz metody asynchronicznej, możesz sprawdzić podpis, aby zobaczyć, co zostanie zwrócone po otrzymaniu wartości zwróconej z metody . Wszystkie asynchroniczne interfejsy API zwracają jeden z następujących typów:
- IAsyncOperation<TResult>
- IAsyncOperationWithProgress<TResult, TProgress>
- IAsyncAction
- IAsyncActionWithProgress<TProgress>
Typ wyniku metody asynchronicznej jest taki sam jak TResult parametr typu. Typy bez TResult elementu nie mają wyniku. Wynik można uznać za brak wartości. W Visual Basic procedura podrzędna jest równoważna metodzie z typem zwracanym void.
W poniższej tabeli przedstawiono przykłady metod asynchronicznych i wymieniono typ zwracany oraz typ wyniku każdego z nich.
| Asynchroniczna metoda | Typ zwracany | Typ wyniku |
|---|---|---|
| SyndicationClient.RetrieveFeedAsync | IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress> | SyndicationFeed |
| FileOpenPicker.PickSingleFileAsync | IAsyncOperation<StorageFile> | Plik pamięci |
| XmlDocument.SaveToFileAsync | IAsyncAction | nieważny |
| InkStrokeContainer.LoadAsync | IAsyncActionWithProgress<UInt64> | nieważny |
| DataReader.LoadAsync | DataReaderLoadOperation, niestandardowa klasa wyników, implementująca interfejs IAsyncOperation<UInt32> | UInt32 |
Note
FileOpenPicker i inne interfejsy API selektora wymagają inicjowania obsługi okien (HWND) w aplikacjach klasycznych WinUI 3. Przed wywołaniem PickSingleFileAsync wywołaj WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd), gdzie hwnd pochodzi z WindowNative.GetWindowHandle(this). Zobacz Wyświetlanie interfejsów API selektora WinUI 3, które wymagają uchwytu okna (HWND).
Metody asynchroniczne zdefiniowane w .NET dla aplikacji Windows mają typ zwracany Task lub Task<TResult>. Metody zwracające zadanie są podobne do metod asynchronicznych, które zwracają metodę IAsyncAction. W każdym przypadku wynik metody asynchronicznej jest void. Zwracany typ Task<TResult> jest podobny do IAsyncOperation<TResult> pod tym względem, że wynik metody asynchronicznej podczas wykonywania zadania jest tego samego typu co parametr typu TResult.
Obsługa błędów
Gdy używasz operatora await do pobierania wyników z metody asynchronicznej, możesz użyć bloku try/catch do obsługi błędów występujących w metodach asynchronicznych, podobnie jak w przypadku metod synchronicznych. W poprzednim przykładzie opakowuje metodę RetrieveFeedAsync i operację await w bloku try/catch , aby obsłużyć błędy po wystąpieniu wyjątku.
Gdy metody asynchroniczne wywołają inne metody asynchroniczne, każda metoda asynchroniczna, która powoduje wyjątek, zostanie rozpropagowana do metod zewnętrznych. Oznacza to, że można umieścić blok try/catch w metodzie najbardziej zewnętrznej, aby przechwycić błędy z zagnieżdżonych metod asynchronicznych. Ponownie jest to podobne do sposobu przechwytywania wyjątków dla metod synchronicznych. Nie można jednak użyć funkcji await w bloku catch .
Tip
Możesz użyć instrukcji await w blokach catch i finally (obsługiwane od wersji C# 6.0).
Podsumowanie i następne kroki
Wzorzec wywoływania metody asynchronicznej, którą pokazano tutaj, jest najprostszym sposobem użycia podczas wywoływania asynchronicznych interfejsów API w procedurze obsługi zdarzeń. Tego wzorca można również użyć podczas wywoływania metody asynchronicznej w metodzie przesłoniętej, która zwraca void lub Sub w Visual Basic.
Podczas napotkania metod asynchronicznych należy pamiętać:
- Zgodnie z konwencją metody asynchroniczne otrzymują nazwy kończące się na "Async".
- Każda metoda używająca operatora await musi mieć swoją deklarację oznaczoną za pomocą słowa kluczowego asynchronicznego .
- Gdy aplikacja znajdzie operator await , aplikacja pozostaje reagująca na interakcję użytkownika, podczas gdy metoda asynchroniczna jest wykonywana.
- Oczekiwanie na wartość zwróconą przez metodę asynchroniczną zwraca obiekt zawierający wynik. W większości przypadków wynik zawarty w wartości zwracanej jest przydatny, a nie wartość zwracana. Typ wartości zawartej w wyniku można znaleźć, sprawdzając zwracany typ metody asynchronicznej.
- Używanie asynchronicznych interfejsów API i wzorców asynchronicznych jest często sposobem poprawy czasu odpowiedzi aplikacji.
Przykład w tym temacie zwraca tekst, który wygląda następująco.
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