Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Windows Phone 8] Async/await et BackgroundWorker

Invalid cross-thread access

Sujet résolu
    12 mars 2013 à 23:27:49

    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 :
    private void _bgw_DoWork(object sender, DoWorkEventArgs e)
    {
        _myObject.SelectAndDownloadAnEvent();
    }

    La méthode SelectAndDownloadAnEvent de mon objet :
    public async Task SelectAndDownloadEvents()
    {        
        return myService.GetAsyncRequestImage(uri); 
    }

    Et finalement, la méthode qui pose problème GetAsyncRequestImage :
    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 !
    • Partager sur Facebook
    • Partager sur Twitter
      13 mars 2013 à 10:43:05

      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 :
      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


      -
      Edité par rolandl 13 mars 2013 à 10:55:27

      • Partager sur Facebook
      • Partager sur Twitter

      [Windows Phone 8] Async/await et BackgroundWorker

      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
      • Editeur
      • Markdown