Udostępnij za pośrednictwem


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.

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ć Taskwartość , 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 intprzykł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 awaitwykonywane. 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 asyncawait 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ą awaitzadania 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 do int wartości obliczonej w tej metodzie.
  • Instrukcja return jest return exampleInt; obiektem całkowitym — fakt, że metoda zwraca Task<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 lub Task<TResult> ).
  • Słowo await kluczowe metody DownloadHomepage bezpośrednio przypisuje się do zmiennej () wintResult przeciwieństwie do poprzedniego przykładu, w którym użyliśmy zmiennej pośredniej Task<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.