Přehled podpory asynchronních operací

Jazyk C# 5 zavedl dvě klíčová slova pro zjednodušení asynchronního programování: asynchronní a await. Tato klíčová slova umožňují napsat jednoduchý kód, který využívá paralelní knihovnu úloh ke spouštění dlouhotrvajících operací (například síťového přístupu) v jiném vlákně a snadný přístup k výsledkům po dokončení. Nejnovější verze Xamarin.iOS a Xamarin.Android podporují asynchronní a await – tento dokument obsahuje vysvětlení a příklad použití nové syntaxe s Xamarinem.

Podpora Async Xamarinu je založená na základu Mono 3.0 a upgraduje profil rozhraní API z mobilní verze Silverlightu, aby byla mobilní verze rozhraní .NET 4.5.

Přehled

Tento dokument představuje nová asynchronní a očekávaná klíčová slova a pak vás provede několika jednoduchými příklady implementace asynchronních metod v Xamarin.iOS a Xamarin.Android.

Podrobnější informace o nových asynchronních funkcích jazyka C# 5 (včetně spousty ukázek a různých scénářů použití) najdete v článku Asynchronní programování.

Ukázková aplikace vytvoří jednoduchý asynchronní webový požadavek (bez blokování hlavního vlákna), pak aktualizuje uživatelské rozhraní staženým kódem HTML a počtem znaků.

The sample application makes a simple asynchronous web request without blocking the main thread then updates the UI with the downloaded html and character count

Asynchronní podpora Xamarinu je založená na základu Mono 3.0 a upgraduje profil rozhraní API z mobilní verze Silverlightu, aby byla mobilní verze rozhraní .NET 4.5.

Požadavky

Funkce C# 5 vyžadují Mono 3.0, které jsou součástí Xamarin.iOS 6.4 a Xamarin.Android 4.8. Zobrazí se výzva k upgradu Mono, Xamarin.iOS, Xamarin.Android a Xamarin.Mac, abyste ho mohli využít.

Použití asynchronního a await

async a await jsou nové jazykové funkce jazyka C#, které fungují ve spojení s knihovnou Parallel Library úloh, aby bylo možné snadno psát kód s vlákny pro provádění dlouhotrvajících úloh bez blokování hlavního vlákna aplikace.

async

Deklarace

Klíčové async slovo se umístí do deklarace metody (nebo na lambda nebo anonymní metodu), která označuje, že obsahuje kód, který může běžet asynchronně, tj. neblokuje vlákno volajícího.

Metoda označená async pomocí by měla obsahovat alespoň jeden výraz nebo příkaz await. Pokud v metodě nejsou k dispozici žádné await příkazy, spustí se synchronně (stejně jako pokud nebyly žádné async modifikátor). Výsledkem bude také upozornění kompilátoru (ale ne chyba).

Návratové typy

Asynchronní metoda by měla vrátit Taskznak , Task<TResult> nebo void.

Zadejte návratový Task typ, pokud metoda nevrací žádnou jinou hodnotu.

Určete Task<TResult> , jestli metoda potřebuje vrátit hodnotu, kde TResult je vrácen typ (například , intnapříklad).

Návratový void typ se používá hlavně pro obslužné rutiny událostí, které ho vyžadují. Kód, který volá asynchronní metody vracející void nemůže await ve výsledku.

Parametry

Asynchronní metody nemohou deklarovat ref ani out parametry.

await

Operátor await lze použít u úlohy uvnitř metody označené jako asynchronní. Způsobí, že metoda v tomto okamžiku zastaví provádění a počká, až se úloha dokončí.

Použití operátoru await neblokuje vlákno volajícího – místo toho se volajícímu vrátí ovládací prvek. To znamená, že volající vlákno není blokováno, takže například vlákno uživatelského rozhraní nebude blokováno při čekání na úlohu.

Po dokončení úlohy metoda pokračuje v provádění ve stejném okamžiku v kódu. To zahrnuje návrat do oboru try-catch-finally bloku try-catch(pokud existuje). příkaz await nelze použít v bloku catch nebo finally.

Přečtěte si další informace o await.

Zpracování výjimek

Výjimky, ke kterým dochází uvnitř asynchronní metody, jsou uloženy v úloze a vyvolány při zpracování úkolu await. Tyto výjimky je možné zachytit a zpracovat uvnitř bloku try-catch.

Zrušení

Asynchronní metody, které trvá delší dobu, by měly podporovat zrušení. Zrušení se obvykle vyvolá takto:

  • Vytvoří se CancellationTokenSource objekt.
  • Instance CancellationTokenSource.Token je předána do zrušenelné asynchronní metody.
  • Zrušení je požadováno voláním CancellationTokenSource.Cancel metody.

Úkol se pak zruší a potvrdí zrušení.

Další informace o zrušení najdete v tématu Jemné ladění asynchronní aplikace (C#).

Příklad

Stáhněte si ukázkové řešení Xamarin (pro iOS i Android) a podívejte se na funkční příklad async a await v mobilních aplikacích. Ukázkový kód je podrobněji popsán v této části.

Zápis asynchronní metody

Následující metoda ukazuje, jak zakódovat metodu asyncawaitpomocí úlohy 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
}

Všimněte si těchto bodů:

  • Deklarace metody obsahuje async klíčové slovo.
  • Návratový typ je Task<int> tak, aby volající kód mohl přistupovat k hodnotě int vypočítané v této metodě.
  • Návratový příkaz je return exampleInt; integer objekt – skutečnost, že metoda vrací Task<int> je součástí vylepšení jazyka.

Volání asynchronní metody 1

Tuto obslužnou rutinu události kliknutí na tlačítko najdete v ukázkové aplikaci pro Android, která volá metodu uvedenou výše:

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
};

Poznámky:

  • Anonymní delegát má předponu asynchronního klíčového slova.
  • Asynchronní metoda DownloadHomepage vrátí Task<int> , který je uložen v proměnné sizeTask.
  • Kód čeká na proměnnou sizeTask. Toto je umístění, kde je metoda pozastavena a ovládací prvek je vrácen do volajícího kódu, dokud asynchronní úloha nedokončí na svém vlastním vlákně.
  • Provádění se při vytvoření úlohy na prvním řádku metody nepozastaví, i když se tam vytvoří úkol. Klíčové slovo await označuje umístění, kde je pozastaveno spuštění.
  • Po dokončení asynchronní úlohy je intResult nastavena a provádění pokračuje v původním vlákně z řádku await.

Volání asynchronní metody 2

V ukázkové aplikaci pro iOS je příklad napsaný trochu jinak, než ukazuje alternativní přístup. Místo použití anonymního delegáta tento příklad deklaruje obslužnou rutinu async události, která je přiřazena jako běžná obslužná rutina události:

GetButton.TouchUpInside += HandleTouchUpInside;

Metoda obslužné rutiny události je pak definována, jak je znázorněno zde:

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 ;
}

Některé důležité body:

  • Metoda je označena jako async , ale vrací void . Obvykle se to provádí jenom u obslužných rutin událostí (jinak byste vrátili Task nebo Task<TResult> ).
  • Klíčové await slovo metody DownloadHomepage přímo přiřadí proměnné (intResult) na rozdíl od předchozího příkladu, kde jsme použili zprostředkující Task<int> proměnnou k odkazování na úlohu. Toto je umístění, kde se ovládací prvek vrátí volajícímu, dokud asynchronní metoda nedokončí v jiném vlákně.
  • Po dokončení a vrácení asynchronní metody se spuštění obnoví, await což znamená, že se vrátí celočíselné výsledky a pak se vykreslí ve widgetu uživatelského rozhraní.

Shrnutí

Použití async a await výrazně zjednodušuje kód potřebný k vytvoření dlouhotrvajících operací na podprocesech na pozadí bez blokování hlavního vlákna. Po dokončení úkolu také usnadňují přístup k výsledkům.

Tento dokument získal přehled nových jazykových klíčových slov a příkladů pro Xamarin.iOS i Xamarin.Android.