另一个线程中的BitmapFrame

时间:2010-03-18 12:09:44

标签: wpf multithreading bitmapframe

我正在使用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(BI)

删除该行(使我的函数无效)也会删除异常。

我没有找到任何解释,或者在后台线程中创建缩略图的更好方法。

2 个答案:

答案 0 :(得分:1)

Lasse,我相信问题的出现是因为您正在UI线程之外执行需要在UI线程内完成的操作。我认为,创建UI元素(BitmapImage,BitmapFrame)并添加到UI容器应该在UI线程上完成。 (如果我在这里错了,有人纠正我。)

有几种方法可以在UI线程上创建这些元素,而不会在过长的时间内阻止应用程序。最简单的可能是使用BackgroundWorker的ProgressChanged事件。在UI线程上调用ProgressChanged,这使它非常适合这种情况。

您可以使用worker的ProgressChanged事件并将其传递给在UserState参数中加载缩略图所需的路径。

答案 1 :(得分:0)

感谢您的投入。它开始寻找另一种解决方案,我想出了这个。

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

不使用任何UI元素..并且工作得很好。 谢谢。 //拉塞