Asynchroniczna pomoc techniczna — omówienie
Język C# 5 wprowadził dwa słowa kluczowe, aby uprościć programowanie asynchroniczne: asynchroniczne i await. Te słowa kluczowe umożliwiają pisanie prostego kodu, który wykorzystuje bibliotekę równoległą zadań do wykonywania długotrwałych operacji (takich jak dostęp do sieci) w innym wątku i łatwe uzyskiwanie dostępu do wyników po zakończeniu. Najnowsze wersje platform Xamarin.iOS i Xamarin.Android obsługują asynchroniczne i await — ten dokument zawiera wyjaśnienia i przykład użycia nowej składni za pomocą platformy Xamarin.
Obsługa Async platformy Xamarin jest oparta na podstawach mono 3.0 i uaktualnia profil interfejsu API z przyjaznej dla urządzeń przenośnych wersji programu Silverlight, aby była przyjazną dla urządzeń przenośnych wersją platformy .NET 4.5.
Omówienie
W tym dokumencie przedstawiono nowe słowa kluczowe asynchroniczne i await, a następnie przedstawiono kilka prostych przykładów implementowania metod asynchronicznych w środowiskach Xamarin.iOS i Xamarin.Android.
Aby zapoznać się z bardziej kompletnym omówieniem nowych funkcji asynchronicznych języka C# 5 (w tym wielu przykładów i różnych scenariuszy użycia), zapoznaj się z artykułem Programowanie asynchroniczne.
Przykładowa aplikacja tworzy proste asynchroniczne żądanie internetowe (bez blokowania głównego wątku), a następnie aktualizuje interfejs użytkownika przy użyciu pobranego kodu HTML i liczby znaków.
Obsługa asynchronityczna platformy Xamarin jest oparta na podstawach platformy Mono 3.0 i uaktualnia profil interfejsu API z przyjaznej dla urządzeń przenośnych wersji programu Silverlight jako przyjaznej dla urządzeń przenośnych wersji platformy .NET 4.5.
Wymagania
Funkcje języka C# 5 wymagają platformy Mono 3.0 dołączonej do platform Xamarin.iOS 6.4 i Xamarin.Android 4.8. Zostanie wyświetlony monit o uaktualnienie aplikacji Mono, Xamarin.iOS, Xamarin.Android i Xamarin.Mac, aby móc z niej korzystać.
Używanie asynchronicznego i await
async
i await
są nowymi funkcjami języka C#, które działają w połączeniu z biblioteką równoległą zadań, aby ułatwić pisanie kodu wątkowego w celu wykonywania długotrwałych zadań bez blokowania głównego wątku aplikacji.
asynchroniczny
Deklaracji
Słowo async
kluczowe jest umieszczane w deklaracji metody (lub w metodzie lambda lub anonimowej), aby wskazać, że zawiera kod, który może być uruchamiany asynchronicznie, tj. nie blokuje wątku obiektu wywołującego.
Metoda oznaczona symbolem async
powinna zawierać co najmniej jedno wyrażenie lub instrukcję await. Jeśli w metodzie nie ma żadnych await
instrukcji, zostanie ona uruchomiona synchronicznie (tak samo jak w przypadku braku async
modyfikatora). Spowoduje to również ostrzeżenie kompilatora (ale nie błąd).
Typy zwracane
Metoda asynchronizna powinna zwrócić Task
wartość , Task<TResult>
lub void
.
Określ typ zwracany Task
, jeśli metoda nie zwraca żadnej innej wartości.
Określ Task<TResult>
, czy metoda musi zwrócić wartość, gdzie TResult
jest zwracany typ (na int
przykład , ).
Zwracany void
typ jest używany głównie w przypadku programów obsługi zdarzeń, które tego wymagają. Kod, który wywołuje metody asynchroniczne zwracające wartość void, nie await
może uzyskać wyniku.
Parametry
Metody asynchroniczne nie mogą deklarować ref
ani out
parametrów.
await
Operator await można zastosować do zadania wewnątrz metody oznaczonej jako asynchronizna. Powoduje to zatrzymanie wykonywania w tym momencie przez metodę i oczekiwanie na zakończenie zadania.
Użycie funkcji await nie blokuje wątku wywołującego — zamiast kontrolki jest zwracana do elementu wywołującego. Oznacza to, że wątek wywołujący nie jest blokowany, więc na przykład wątek interfejsu użytkownika nie zostanie zablokowany podczas oczekiwania na zadanie.
Po zakończeniu zadania metoda wznawia wykonywanie w tym samym punkcie w kodzie. Obejmuje to powrót do zakresu try-catch-finally bloku try-catch-finally (jeśli istnieje). Nie można użyć await w elemecie catch lub w końcu bloku.
Przeczytaj więcej na temat await.
Obsługa wyjątków
Wyjątki występujące wewnątrz metody asynchronicznej są przechowywane w zadaniu i zgłaszane, gdy zadanie jest await
wykonywane. Te wyjątki można przechwycić i obsłużyć wewnątrz bloku try-catch.
Anulowanie
Metody asynchroniczne, które zajmują dużo czasu, powinny obsługiwać anulowanie. Zazwyczaj anulowanie jest wywoływane w następujący sposób:
- Zostanie
CancellationTokenSource
utworzony obiekt. - Wystąpienie
CancellationTokenSource.Token
jest przekazywane do metody asynchronicznej z możliwością anulowania. - Żądanie anulowania jest wymagane przez wywołanie
CancellationTokenSource.Cancel
metody .
Następnie zadanie anuluje się i potwierdza anulowanie.
Aby uzyskać więcej informacji na temat anulowania, zobacz Dostosowywanie aplikacji asynchronicznych (C#).
Przykład
Pobierz przykład (dla systemów iOS i Android), aby zobaczyć działający przykład i async
await
w aplikacjach mobilnych. Przykładowy kod został omówiony bardziej szczegółowo w tej sekcji.
Pisanie metody asynchronicznej
Poniższa metoda pokazuje, jak kodować metodę async
za pomocą await
zadania ed:
public async Task<int> DownloadHomepage()
{
var httpClient = new HttpClient(); // Xamarin supports HttpClient!
Task<string> contentsTask = httpClient.GetStringAsync("https://visualstudio.microsoft.com/xamarin"); // async method!
// await! control returns to the caller and the task continues to run on another thread
string contents = await contentsTask;
ResultEditText.Text += "DownloadHomepage method continues after async call. . . . .\n";
// After contentTask completes, you can calculate the length of the string.
int exampleInt = contents.Length;
ResultEditText.Text += "Downloaded the html and found out the length.\n\n\n";
ResultEditText.Text += contents; // just dump the entire HTML
return exampleInt; // Task<TResult> returns an object of type TResult, in this case int
}
Zwróć uwagę na następujące kwestie:
- Deklaracja metody zawiera
async
słowo kluczowe . - Zwracany typ jest
Task<int>
taki, aby kod wywołujący mógł uzyskać dostęp doint
wartości obliczonej w tej metodzie. - Instrukcja return jest
return exampleInt;
obiektem całkowitym — fakt, że metoda zwracaTask<int>
, jest częścią ulepszeń języka.
Wywoływanie metody asynchronicznej 1
Ten przycisk kliknij procedurę obsługi zdarzeń można znaleźć w przykładowej aplikacji systemu Android, aby wywołać metodę omówioną powyżej:
GetButton.Click += async (sender, e) => {
Task<int> sizeTask = DownloadHomepage();
ResultTextView.Text = "loading...";
ResultEditText.Text = "loading...\n";
// await! control returns to the caller
var intResult = await sizeTask;
// when the Task<int> returns, the value is available and we can display on the UI
ResultTextView.Text = "Length: " + intResult ;
// "returns" void, since it's an event handler
};
Uwagi:
- Delegat anonimowy ma prefiks słowa kluczowego asynchronicznego.
- Metoda asynchroniczna DownloadHomepage zwraca wartość int> task<przechowywaną w zmiennej sizeTask.
- Kod oczekuje na zmienną sizeTask. Jest to lokalizacja, w którą metoda jest zawieszona, a kontrolka jest zwracana do kodu wywołującego do momentu zakończenia zadania asynchronicznego we własnym wątku.
- Wykonanie nie jest wstrzymane, gdy zadanie jest tworzone w pierwszym wierszu metody, mimo że zadanie jest tam tworzone. Słowo kluczowe await oznacza lokalizację, w której wykonywanie jest wstrzymane.
- Po zakończeniu zadania asynchronicznego parametr intResult jest ustawiany i wykonywanie będzie kontynuowane w oryginalnym wątku z wiersza await.
Wywoływanie metody asynchronicznej 2
W przykładowej aplikacji systemu iOS przykład jest napisany nieco inaczej, aby zademonstrować alternatywne podejście. Zamiast używać anonimowego delegata, ten przykład deklaruje procedurę obsługi zdarzeń przypisaną async
jak zwykła procedura obsługi zdarzeń:
GetButton.TouchUpInside += HandleTouchUpInside;
Metoda obsługi zdarzeń jest następnie zdefiniowana, jak pokazano poniżej:
async void HandleTouchUpInside (object sender, EventArgs e)
{
ResultLabel.Text = "loading...";
ResultTextView.Text = "loading...\n";
// await! control returns to the caller
var intResult = await DownloadHomepage();
// when the Task<int> returns, the value is available and we can display on the UI
ResultLabel.Text = "Length: " + intResult ;
}
Niektóre ważne kwestie:
- Metoda jest oznaczona jako ,
async
ale zwraca wartośćvoid
. Zazwyczaj jest to wykonywane tylko w przypadku procedur obsługi zdarzeń (w przeciwnym razie należy zwrócić wartośćTask
lubTask<TResult>
). - Słowo
await
kluczowe metodyDownloadHomepage
bezpośrednio przypisuje się do zmiennej () wintResult
przeciwieństwie do poprzedniego przykładu, w którym użyliśmy zmiennej pośredniejTask<int>
do odwołowania się do zadania. Jest to lokalizacja, w której kontrolka jest zwracana do elementu wywołującego do momentu zakończenia metody asynchronicznej w innym wątku. - Po zakończeniu i powrocie metody asynchronicznej wykonywanie zostanie wznowione
await
, co oznacza, że wynik liczby całkowitej jest zwracany, a następnie renderowany w widżecie interfejsu użytkownika.
Podsumowanie
Użycie async i await znacznie upraszcza kod wymagany do zduplikowania długotrwałych operacji na wątkach w tle bez blokowania głównego wątku. Ułatwiają one również uzyskiwanie dostępu do wyników po zakończeniu zadania.
Ten dokument zawiera omówienie nowych słów kluczowych języka i przykładów dla platform Xamarin.iOS i Xamarin.Android.
Linki powiązane
- Wywołania zwrotne jako instrukcja Przejdź do naszej generacji
- MapKitSearch (iOS) (przykład)
- Programowanie asynchroniczne
- Dostrajanie aplikacji asynchronicznych (C#)
- Await, and UI, and deadlocks! O rany!
- Przetwarzanie zadań po ich zakończeniu)
- Wzorzec asynchroniczny oparty na zadaniach (TAP)
- Asynchrony w języku C# 5 (blog Erica Lipperta) — o wprowadzeniu słów kluczowych