BitmapFrame в другом потоке - PullRequest
1 голос
/ 18 марта 2010

Я использую WPF BackgroundWorker для создания миниатюр. Моя рабочая функция выглядит так:

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

Когда эта функция завершена и перед запуском функции «Завершено» BackgroundWorker, я вижу в окне вывода Vs2008, что генерируется исключение. Похоже:

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

Количество генерируемых исключений равно числу генерируемых миниатюр.

Используя метод проб и ошибок, я изолировал проблему: BitmapFrame.Create (би)

Удаление этой строки (делает мою функцию бесполезной) также удаляет исключение.

Я не нашел никакого объяснения этому или лучшего способа создания миниатюр в фоновом потоке.

Ответы [ 2 ]

1 голос
/ 18 марта 2010

Лассе, я полагаю, что проблема возникает из-за того, что вы выполняете действия вне потока пользовательского интерфейса, которые необходимо выполнить в потоке пользовательского интерфейса. Я полагаю, что создание элементов пользовательского интерфейса (BitmapImage, BitmapFrame) и добавление в контейнеры пользовательского интерфейса должно выполняться в потоке пользовательского интерфейса. (Кто-то поправит меня, если я здесь не прав).

Есть несколько способов создать эти элементы в потоке пользовательского интерфейса, не блокируя приложение в течение чрезмерного периода времени. Наиболее простым, вероятно, является использование события BackgroundWorker's ProgressChanged. ProgressChanged вызывается в потоке пользовательского интерфейса, что делает его идеальным для этой ситуации.

Вы можете использовать событие ProgressChanged работника и передать ему путь, необходимый для загрузки миниатюры в аргументе UserState.

0 голосов
/ 19 марта 2010

Спасибо за ваш вклад. Это заставило начать искать другие решения, и я придумаю это.

       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)
        {
        } 

Не использует никаких элементов пользовательского интерфейса .. и работает хорошо. Благодарю. // Ласс

...