Vue d’ensemble de la prise en charge asynchrone

C# 5 a introduit deux mot clé pour simplifier le programmation asynchrone : asynchrone et await. Ces mot clé vous permettent d’écrire du code simple qui utilise la bibliothèque parallèle de tâches pour exécuter des opérations longues (telles que l’accès réseau) dans un autre thread et accéder facilement aux résultats à la fin. Les dernières versions de Xamarin.iOS et Xamarin.Android prennent en charge async et await : ce document fournit des explications et un exemple d’utilisation de la nouvelle syntaxe avec Xamarin.

La prise en charge asynchrone de Xamarin repose sur la base de Mono 3.0 et met à niveau le profil d’API à partir de la version mobile de Silverlight pour être une version mobile de .NET 4.5.

Vue d’ensemble

Ce document présente la nouvelle async et attend les mot clé, puis décrit quelques exemples simples d’implémentation de méthodes asynchrones dans Xamarin.iOS et Xamarin.Android.

Pour une discussion plus complète sur les nouvelles fonctionnalités asynchrones de C# 5 (y compris un grand nombre d’exemples et différents scénarios d’utilisation), reportez-vous à l’article Programmation asynchrone.

L’exemple d’application effectue une requête web asynchrone simple (sans bloquer le thread principal), puis met à jour l’interface utilisateur avec le nombre de caractères et html téléchargés.

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

La prise en charge asynchrone de Xamarin repose sur la base de Mono 3.0 et met à niveau le profil d’API de la version mobile de Silverlight pour être une version mobile de .NET 4.5.

Spécifications

Les fonctionnalités C# 5 nécessitent Mono 3.0 inclus dans Xamarin.iOS 6.4 et Xamarin.Android 4.8. Vous serez invité à mettre à niveau votre mono, Xamarin.iOS, Xamarin.Android et Xamarin.Mac pour en tirer parti.

Utilisation d’async &await

async et await sont de nouvelles fonctionnalités de langage C# qui fonctionnent conjointement avec la bibliothèque parallèle de tâches pour faciliter l’écriture de code threadé pour effectuer des tâches de longue durée sans bloquer le thread principal de votre application.

asynchrone

Déclaration

Le async mot clé est placé dans une déclaration de méthode (ou sur une méthode lambda ou anonyme) pour indiquer qu’il contient du code qui peut s’exécuter de manière asynchrone, c’est-à-dire ne pas bloquer le thread de l’appelant.

Une méthode marquée avec async doit contenir au moins une expression ou une instruction await. Si aucune instruction n’est await présente dans la méthode, elle s’exécute de façon synchrone (identique à si aucun modificateur n’a async été présent). Cela entraîne également un avertissement du compilateur (mais pas une erreur).

Types de retour

Une méthode asynchrone doit retourner un Task, Task<TResult> ou void.

Spécifiez le Task type de retour si la méthode ne retourne aucune autre valeur.

Spécifiez Task<TResult> si la méthode doit retourner une valeur, où TResult est le type retourné (par exemple, un int, par exemple).

Le void type de retour est utilisé principalement pour les gestionnaires d’événements qui en ont besoin. Le code qui appelle des méthodes asynchrones void-retour ne peut pas await sur le résultat.

Paramètres

Les méthodes asynchrones ne peuvent pas déclarer ou out paramètresref.

await

L’opérateur await peut être appliqué à une tâche à l’intérieur d’une méthode marquée comme asynchrone. Elle entraîne l’arrêt de l’exécution de la méthode à ce stade et attend la fin de la tâche.

L’utilisation d’await ne bloque pas le thread de l’appelant. Le contrôle est plutôt retourné à l’appelant. Cela signifie que le thread appelant n’est pas bloqué. Par exemple, le thread d’interface utilisateur n’est pas bloqué lors de l’attente d’une tâche.

Une fois la tâche terminée, la méthode reprend l’exécution au même point dans le code. Cela inclut le retour à l’étendue try d’un bloc try-catch-finally (le cas échéant). await ne peut pas être utilisé dans un bloc catch ou enfin.

En savoir plus sur await.

Gestion des exceptions

Les exceptions qui se produisent à l’intérieur d’une méthode asynchrone sont stockées dans la tâche et levées lorsque la tâche est awaitexécutée. Ces exceptions peuvent être interceptées et gérées à l’intérieur d’un bloc try-catch.

Annulation

Les méthodes asynchrones qui prennent beaucoup de temps doivent prendre en charge l’annulation. En règle générale, l’annulation est appelée comme suit :

  • Un CancellationTokenSource objet est créé.
  • L’instance CancellationTokenSource.Token est passée à une méthode asynchrone annulable.
  • L’annulation est demandée en appelant la CancellationTokenSource.Cancel méthode.

La tâche s’annule ensuite et reconnaît l’annulation.

Pour plus d’informations sur l’annulation, consultez Réglage de votre application Async (C#).

Exemple

Téléchargez l’exemple de solution Xamarin (pour iOS et Android) pour voir un exemple de travail et awaitasync dans les applications mobiles. L’exemple de code est abordé plus en détail dans cette section.

Écriture d’une méthode asynchrone

La méthode suivante montre comment coder une async méthode avec une awaittâche 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
}

Prenez note des points suivants :

  • La déclaration de méthode inclut la async mot clé.
  • Le type de retour est Task<int> de sorte que le code appelant peut accéder à la int valeur calculée dans cette méthode.
  • L’instruction return est return exampleInt; un objet entier : le fait que la méthode retourne Task<int> fait partie des améliorations du langage.

Appel d’une méthode asynchrone 1

Ce bouton cliquez sur le gestionnaire d’événements dans l’exemple d’application Android pour appeler la méthode décrite ci-dessus :

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

Remarques :

  • Le délégué anonyme a le préfixe mot clé asynchrone.
  • La méthode asynchrone DownloadHomepage retourne un int> Task<stocké dans la variable sizeTask.
  • Le code attend sur la variable sizeTask. Il s’agit de l’emplacement où la méthode est suspendue et que le contrôle est retourné au code appelant jusqu’à ce que la tâche asynchrone se termine sur son propre thread.
  • L’exécution ne s’interrompt pas lorsque la tâche est créée sur la première ligne de la méthode, malgré la tâche en cours de création. L’mot clé await signifie l’emplacement où l’exécution est suspendue.
  • Une fois la tâche asynchrone terminée, intResult est défini et l’exécution se poursuit sur le thread d’origine, à partir de la ligne await.

Appel d’une méthode asynchrone 2

Dans l’exemple d’application iOS, l’exemple est écrit légèrement différemment pour illustrer une autre approche. Au lieu d’utiliser un délégué anonyme, cet exemple déclare un gestionnaire d’événements async affecté comme un gestionnaire d’événements standard :

GetButton.TouchUpInside += HandleTouchUpInside;

La méthode du gestionnaire d’événements est ensuite définie comme indiqué ici :

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

Quelques points importants :

  • La méthode est marquée comme async étant mais renvoie void . Cela est généralement effectué uniquement pour les gestionnaires d’événements (sinon vous retourneriez une Task ou Task<TResult> ).
  • Le await mot clé de la DownloadHomepage méthode affecte directement à une variable (intResult) contrairement à l’exemple précédent où nous avons utilisé une variable intermédiaire Task<int> pour référencer la tâche. Il s’agit de l’emplacement où le contrôle est retourné à l’appelant jusqu’à ce que la méthode asynchrone soit terminée sur un autre thread.
  • Lorsque la méthode asynchrone se termine et retourne, l’exécution reprend au niveau du await résultat entier retourné, puis rendu dans un widget d’interface utilisateur.

Résumé

L’utilisation d’async et await simplifie considérablement le code requis pour générer des opérations longues sur des threads d’arrière-plan sans bloquer le thread principal. Ils facilitent également l’accès aux résultats une fois la tâche terminée.

Ce document a donné une vue d’ensemble des nouvelles mot clé de langage et des exemples pour Xamarin.iOS et Xamarin.Android.