IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Phone .NET Discussion :

[WP8] Async/await, BackgroundWorker et Invalid cross-thread access


Sujet :

Windows Phone .NET

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    128
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2011
    Messages : 128
    Points : 86
    Points
    86
    Par défaut [WP8] Async/await, BackgroundWorker et Invalid cross-thread access
    Bonjour,

    Je développe actuellement une application qui fait appel à des tâches asynchrones et des tâches de fond.

    Dans mon application, je souhaite afficher des photos les unes après les autres.

    Au niveau du chargement et de l'affichage, les étapes sont les suivantes :
    1. Affichage d'un message de chargement
    2. Téléchargement et mise en "cache" de 5 photos
    3. Suppression du message de chargement
    4. Affichage de la première photo
    5. Demande d'affichage de la seconde photo
    6. Téléchargement et mise en "cache" en arrière plan d'une 6ème photo
    7. Affichage de la deuxième photo


    Les étapes 4 à 7 se répètent alors jusqu'à épuisement des photos.

    Pour les étapes 1 à 3, je n'ai aucun soucis. J'utilise les mots clefs async/await pour attendre la fin de mon téléchargement asynchrone.

    J'ai cependant un problème avec l'étape 6. En effet, dans cette étape, je ne souhaite pas attendre la fin de mon téléchargement. Cette étape se fait en arrière plan. Je me suis donc tourné vers un BackgroundWorker.

    Le problème est qu'au moment de lancer mon BackgroundWorker, j'ai une erreur. Voici le Message et le StackTrace :

    Une exception de première chance de type 'System.UnauthorizedAccessException' s'est produite dans System.Windows.ni.dll
    Une exception de type 'System.UnauthorizedAccessException' s'est produite dans System.Windows.ni.dll et n'a pas été traitée avant une limite managée/native
    at MS.Internal.XcpImports.CheckThread()
    at System.Windows.DependencyObject..ctor(UInt32 nativeTypeIndex, IntPtr constructDO)
    at System.Windows.Media.Imaging.BitmapImage..ctor()
    at myService.<GetAsyncRequestImage>d__5.MoveNext()

    Invalid cross-thread access.
    Voici quelques extraits de code.

    La méthode DoWork de mon BackgroundWorker :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    private void _bgw_DoWork(object sender, DoWorkEventArgs e)
    {
        _myObject.SelectAndDownloadAnEvent();
    }
    La méthode SelectAndDownloadAnEvent de mon objet :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public async Task SelectAndDownloadEvents()
    {         
        return myService.GetAsyncRequestImage(uri);  
    }
    Et finalement, la méthode qui pose problème GetAsyncRequestImage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    public static BitmapImage GetAsyncRequestImage(Uri uri)
    {
        try
        {
            var image = new BitmapImage();
     
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                var request = (HttpWebRequest) WebRequest.Create(uri);
                request.BeginGetResponse(result =>
                {
                    using (var sr = request.EndGetResponse(result))
                    {
                        image.SetSource(sr.GetResponseStream());
                     }
                 }, null);
             });
     
            return image;
        }
        catch (Exception)
        {
            return null;
        }
    }
    Bien évidemment il ne s'agit que d'extraits de code. Par conséquent, certains mots clefs comme async ne sont pas exploités dans ce cas mais peuvent l'être dans d'autres. J'ai donc laissé les signatures de mes fonctions en l'état.

    Je ne comprends pas trop l'origine du problème. En effet, comme lu un peu partout sur internet, j'ai ajouté l'encapsulation dans le dispatcher qui dans la théorie mon problème mais sans succès.

    J'ai également tenté d'encapsuler le contenu de ma méthode dans un lock, mais une fois de plus sans succès.

    Merci d'avance pour votre aide !

  2. #2
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    128
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2011
    Messages : 128
    Points : 86
    Points
    86
    Par défaut
    Bonjour,

    J'ai du nouveau. Il semblerait que le constructeur d'un BitmapImage doit forcément être appelé dans le thread de l'UI.

    J'ai donc modifié ma fonction de la façon suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    BitmapImage image = null;
                    AutoResetEvent bitmapInitialization = new AutoResetEvent(false);
     
                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        image = new BitmapImage();
     
                        var request = (HttpWebRequest)WebRequest.Create(uri);
                        request.Method = "GET";
     
                        request.BeginGetResponse(result =>
                        {
                            var response = request.EndGetResponse(result);
                            using (var stream = response.GetResponseStream())
                            {
                                image.SetSource(stream);
                                bitmapInitialization.Set();
                            }
                        }, null);
                    });
     
                    bitmapInitialization.WaitOne();
                    return image;
    Mais j'ai toujours une erreur sur la ligne image.SetSource(stream);

    Une exception de type 'System.IO.FileNotFoundException' s'est produite dans mscorlib.ni.dll et n'a pas été traitée avant une limite managée/native
    Une exception de première chance de type 'System.UnauthorizedAccessException' s'est produite dans System.Windows.ni.dll
    Une exception de type 'System.UnauthorizedAccessException' s'est produite dans System.Windows.ni.dll mais n'a pas été gérée dans le code utilisateur

  3. #3
    Membre expert
    Avatar de GuruuMeditation
    Homme Profil pro
    .Net Architect
    Inscrit en
    Octobre 2010
    Messages
    1 705
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : Belgique

    Informations professionnelles :
    Activité : .Net Architect
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2010
    Messages : 1 705
    Points : 3 568
    Points
    3 568
    Par défaut
    Le callback de BeginGetResponse n'est pas sur le même thread.

    Enlève ton Dispatcher.BeginInvoke et remplace image.Setsource par un truc style :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
     Deployment.Current.Dispatcher.BeginInvoke(() =>
                                                                          {
                                                                              image = new BitmapImage();
                                                                              image.SetSource(ms);
     
     
                                                                          });
    Microsoft MVP : Windows Platform

    MCPD - Windows Phone Developer
    MCPD - Windows Developer 4

    http://www.guruumeditation.net

    “If debugging is the process of removing bugs, then programming must be the process of putting them in.”
    (Edsger W. Dijkstra)

Discussions similaires

  1. [Débutant] BackgroundWorker + Cross-Thread
    Par Whippet dans le forum C#
    Réponses: 5
    Dernier message: 02/11/2013, 13h34
  2. [WP 7.1 beta 2] Message d'erreur Invalid cross-thread access
    Par Immobilis dans le forum Windows Phone
    Réponses: 3
    Dernier message: 28/07/2011, 17h21
  3. [C#]Cross-thread operation not valid
    Par hrp dans le forum Windows Forms
    Réponses: 17
    Dernier message: 31/07/2007, 16h36
  4. [VB.NET]Erreur "invalid cross-thread operation"
    Par NicolasJolet dans le forum Windows Forms
    Réponses: 6
    Dernier message: 05/04/2006, 12h38
  5. [VB.NET 2.0] Cross-Thread Exception
    Par guillaume1998 dans le forum Windows Forms
    Réponses: 13
    Dernier message: 30/01/2006, 18h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo