1 votes

BitmapFrame dans un autre fil

J'utilise un BackgroundWorker WPF pour créer des vignettes. Ma fonction de travailleur ressemble à ceci :

private void work(object sender, DoWorkEventArgs e)
{ 
  try
  {
    var paths = e.Argument as string[];
    var boxList = new List<BoxItem>();
    foreach (string path in paths)
    {                   
       if (!string.IsNullOrEmpty(path))
       {
        FileInfo info = new FileInfo(path);
        if (info.Exists && info.Length > 0)
        {
           BitmapImage bi = new BitmapImage();
           bi.BeginInit();
           bi.DecodePixelWidth = 200;
           bi.CacheOption = BitmapCacheOption.OnLoad;
           bi.UriSource = new Uri(info.FullName);
           bi.EndInit();
           var item = new BoxItem();
           item.FilePath = path;
           MemoryStream ms = new MemoryStream();
           PngBitmapEncoder encoder = new PngBitmapEncoder();
           encoder.Frames.Add(BitmapFrame.Create(bi));  
           encoder.Save(ms);
           item.ThumbNail = ms.ToArray();
           ms.Close();
           boxList.Add(item);
        }
      }
    }
    e.Result = boxList;
  }
  catch (Exception ex)
  { 
    //nerver comes here
  }
}

Lorsque cette fonction est terminée et avant que la fonction "Completed" de BackgroundWorker soit lancée, je peux voir sur la fenêtre de sortie de Vs2008, qu'une exception est générée. Cela ressemble à :

 A first chance exception of type 'System.NotSupportedException' occurred in PresentationCore.dll

Le nombre d'exceptions générées est égal au nombre de vignettes à générer.

En utilisant la méthode "essais et erreurs", j'ai isolé le problème : BitmapFrame.Create(bi)

La suppression de cette ligne (qui rend ma fonction inutile) supprime également l'exception.

Je n'ai pas trouvé d'explication à cela, ni de meilleure méthode pour créer des vignettes dans un fil de fond.

1voto

Ed Gonzalez Points 1436

Lasse, je pense que le problème vient du fait que vous effectuez des actions en dehors du thread de l'interface utilisateur alors qu'elles devraient être effectuées dans le thread de l'interface utilisateur. Je pense que la création d'éléments d'interface utilisateur (BitmapImage, BitmapFrame) et l'ajout à des conteneurs d'interface utilisateur doivent être effectués dans le thread d'interface utilisateur. (Quelqu'un me corrige si je me trompe ici).

Il existe quelques moyens de créer ces éléments sur le thread de l'interface utilisateur sans bloquer l'application pendant une période excessive. La plus simple consiste probablement à utiliser l'événement ProgressChanged du BackgroundWorker. ProgressChanged est invoqué sur le thread de l'interface utilisateur, ce qui le rend parfait pour cette situation.

Vous pouvez utiliser l'événement ProgressChanged du travailleur et lui transmettre le chemin nécessaire pour charger une vignette dans l'argument UserState.

0voto

Merci pour votre contribution. J'ai commencé à chercher d'autres solutions et j'ai trouvé celle-ci.

       try
        {
            var paths = e.Argument as string[];
            var boxList = new List<BoxItem>();

            foreach (string path in paths)
            {
                using (Image photoImg = Image.FromFile(path))
                {
                    int newWidth = 200;
                    int width = newWidth;
                    int height = (photoImg.Height * newWidth) / photoImg.Width;

                    var thumbnail = new Bitmap(width, height);

                    using (Graphics g = Graphics.FromImage((System.Drawing.Image)thumbnail))
                    {
                        g.DrawImage(photoImg, 0, 0, width, height);
                        using (var ms = new System.IO.MemoryStream())
                        {
                            var item = new BoxItem();
                            item.FilePath = path;

                            thumbnail.Save(ms, System.Drawing.Imaging.ImageFormat.Png);

                            item.ThumbNail = ms.ToArray();
                            boxList.Add(item);
                        }
                    }
                }
            }
            e.Result = boxList;
        }

        catch (Exception exp)
        {
        } 

Je n'utilise pas d'éléments d'interface utilisateur et cela fonctionne bien. Merci. //lasse

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X