Requêtes http et violation de threads

L’une des principales caractéristiques d’un smartphone tel que Windows Phone 7 est d’être constamment connecté à Internet. Partant de ce fait, il est tout naturel, qu’en tant que développeurs, nous cherchions à exploiter les nombreux avantages qu’offre cette connexion Internet, en interagissant par exemple avec un serveur de base de données. Seulement, sur le web, de nombreuses technologies cohabitent et il se peut que votre serveur ne puisse communiquer que via des requêtes http (envoi des données en GET ou POST). Bien que très simple d’utilisation, l’objet WebClient présente tout de même quelques limites. L’alternative à ce dernier est d’utiliser l’objet « httpWebRequest », qui est bien plus complet (meilleur gestion des cookies). Néanmoins, les appels asynchrones que ce dernier effectue empêchent d’interagir directement avec l’interface utilisateur : une exception de type « invalid cross-thread access » est levée.

 

Pourquoi une exception est-elle déclenchée ?

Ce qu’il faut savoir en premier lieu est que Windows Phone 7 (et il en va de même pour Silverlight) ne permets d’effectuer que des appels asynchrones. Partant de ce constat, il est important de souligner que le fait de lancer une requête http en asynchrone lance un nouveau fil d’exécution (appelé « Thread ») pour votre application, en plus du Thread d’exécution principal. Désormais toute fonction appelée par le Thread secondaire va rester dans ce Thread. Prenons un exemple concret pour illustrer tout ça :

private static HttpWebRequest _webRequest;

private static HttpWebResponse _reponse;

 

public void LancerAppelAsynchrone()

{

     maProgressBar.Visibility = System.Windows.Visibility.Visible;

     Uri AdresseAppel = new Uri("http://www.adresseDeVotreAppel.com");

 

     _webRequest = (HttpWebRequest)WebRequest.Create(AdresseAppel);

     _webRequest.Method = "GET";

 

     _webRequest.BeginGetResponse(FinReceptionDonneesAsync, _webRequest);

}

private void FinReceptionDonneesAsync(IAsyncResult asynchronousResult)

{

    maProgressBar.Visibility = System.Windows.Visibility.Collapsed;

}

 

Le fait de vouloir cacher notre ProgressBar va donc systématiquement lancer une exception de type « invalid cross-thread access », car les éléments de l’interface ont été instanciés dans le thread principal et dépendent donc de ce dernier. Or la fonction « FinReceptionDonneesAsync » dépends du thread secondaire, ayant été lancé de l’appel à la méthode « BeginGetResponse ». Nous ne pouvons tout simplement pas interagir avec un objet instancié dans un thread qui n’est pas celui dans lequel nous tentons de masquer notre ProgressBar. Là encore afin de mieux comprendre, je vous invite à jeter un coup d’œil à l’illustration ci-dessous.

schema threads

 

Comment faire pour régler ce problème ?

Il suffit d’indiquer à votre programme que l’instruction qui cache la ProgressBar doit être exécutée dans le Thread principal. Pour ce faire, vous pouvez utiliser la petite classe ci-dessous.

public static class UIThread

{

     private static readonly Dispatcher Dispatcher;

 

     static UIThread()

     {

         Dispatcher = Deployment.Current.Dispatcher;

     }

 

     public static void Invoke(Action __action)

     {

         if (Dispatcher.CheckAccess())

            __action.Invoke();

         else

            Dispatcher.BeginInvoke(__action);

     }

}

 

Le constructeur de cette classe statique va stocker une référence au Dispatcher pour l’application exécutée dans la variable membre de la classe.

La méthode « Invoke » va vérifier si l’action que vous tentez d’exécuter est dans le Thread principal ou non. Si c’est le cas, elle va simplement exécuter l’instruction demandée, sinon elle va la lancer dans le Thread principal, dont la référence a été stockée au préalable par le constructeur.

Désormais, il nous suffit simplement d’utiliser notre classe de la façon suivante, afin de cacher notre ProgressBar sans encombre :

private void FinReceptionDonneesAsync(IAsyncResult asynchronousResult)

{

UIThread.Invoke(() => maProgressBar.Visibility = System.Windows.Visibility.Collapsed);

}

 

Limites de cette méthode

Dans la majorité des cas d’utilisation, la solution proposée ci-dessus convient tout à fait. Elle est simple et très facile à mettre en place dans vos applications. Néanmoins elle présente certaines limites et ne permet pas de tout faire. Elle ne permet pas, par exemple, d’instancier un nouvel objet d’interface utilisateur (prenons l’exemple d’un simple TextBlock). Ainsi, le code suivant va lever la même exception que précédemment.

private void FinReceptionDonneesAsync(IAsyncResult asynchronousResult)

{

     TextBlock tbl = new TextBlock();

}

 

Bien entendu, le plus logique serait d’utiliser notre classe « UIThread », ce qui donnerait ce qui suit :

private void FinReceptionDonneesAsync(IAsyncResult asynchronousResult)

{

    TextBlock tbl;

    UIThread.Invoke(() => tbl = new TextBlock());

}

 

Néanmoins, votre objet sera toujours « null », il n’est pas possible d’instancier un objet quel qu’il soit avec UIThread. Il convient donc d’utiliser le code suivant :

private void FinReceptionDonneesAsync(IAsyncResult asynchronousResult)

{

    using (AutoResetEvent are = new AutoResetEvent(false))

    {

         Deployment.Current.Dispatcher.BeginInvoke(() =>

         {

              TextBlock tbl = new TextBlock();

              tbl.Text = "Ca marche !";

              LayoutRoot.Children.Add(tbl);

              are.Set();

          });

          are.WaitOne();

     }

}

Le code ci-dessus permet de mettre en pause le Thread principal et donc d’exécuter le code contenu dans la méthode « BeginInvoke() », pendant que ce dernier est en stand-by. Cela permet donc d’avoir accès aux contrôles de l’interface utilisateur et d’éviter les exceptions de violation de Threads.


Vous pouvez désormais instancier de nouveaux objets et interagir avec l’interface utilisateur de votre application, tout en effectuant des requêtes http (ou tout autre appel asynchrone levant un « invalid cross-thread access »).

le virtuels et aux

le virtuels et aux simulations de tir.(lien en anglais) pour supprimer le programme de son ordinateur.?? sac louis vuitton "L'objectif est ainsi de prendre des parts de marché à la voiture, par rapport à laquelle l'autocar représente un moyen de transport nettement plus écologique et très sécurisé".Le candidat s'est également réjoui d'avoir irrité la gauche et les syndicats en annon?sac vuitton Celle-ci promet en effet une machine "immunisée contre les virus". sacs louis vuittonler l'immigration, améliorer la sécurité, changer l'Europe pour qu'elle ne soit plus une "passoire",? Je parle aussi bien à ceux qui ont voté Fran? louis vuitton site officiel: se faire passer pour un no life?Stora :? louis vuitton pas cherSelon Dr?

Sorry but, viagra online ,

Sorry but,
viagra online , generic viagra ,

Perfect! buy viagra online ,

Perfect!
buy viagra online ,

Perfect! buy cheap viagra ,

Perfect!
buy cheap viagra ,

Sorry but, ambien pharmacy ,

Hello! ambien , adipex no

Perfect! generic xanax ,

Publier un nouveau commentaire

Le contenu de ce champ sera maintenu privé et ne sera pas affiché publiquement.
  • Les adresses de pages web et de courriels sont transformées en liens automatiquement.
  • Tags HTML autorisés : <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Les lignes et les paragraphes vont à la ligne automatiquement.
  • You can enable syntax highlighting of source code with the following tags: [code], [blockcode], [c], [cpp], [css], [drupal5], [drupal6], [java], [javascript], [php], [python], [ruby].

Plus d'informations sur les options de formatage

CAPTCHA visuel
Entrez les caractères (sans espace) affichés dans l'image.
© 2011 Copyright cigo-developpement.fr