TiffBitmapEncoder:使位图编码异步

时间:2013-09-13 18:25:24

标签: c# multithreading backgroundworker bitmapencoder

问题:如何相对于主线程异步保存/压缩位图图像(其中几个堆叠在tiff文件中)?

我的设置:(同步和慢速工作解决方案:执行压缩时,线程会停留几秒钟。我负担不起。)

 ...in the body of a window class 

private void afunction(){ 
     //called with a given frequency and updating this.colorBitmap
     ...
     this.colorBitmap = something;          
     savePictureStackTiff();
}

private int stack_pict_count = 0;
private int PICT_PER_FILE = 45;        
private TiffBitmapEncoder encoder;        

private string savePictureStackTiff()
{
      initializeTiffEncoder();
      //make a local copy of the image I want to put in the tiff binder
      WriteableBitmap localCopy = new WriteableBitmap(this.colorBitmap);    

      encoder.Frames.Add(BitmapFrame.Create(localCopy));  

      stack_pict_count++;
      if (stack_pict_count % PICT_PER_FILE == 0) 
      //Once I have enough files stacked I ask for compression
      {              
          stack_pict_count = 0;
          pict_metadata = "";            
          try
          {
              using (FileStream fs = new FileStream(path, FileMode.Create))
              {
                  encoder.Save(fs); //<<<== LINE WHICH I'D LIKE TO BE RUN ASYNC
              }                    
           }
           catch (IOException)
           {}               
        }
 }

 private void initializeTiffEncoder()
 {
    if (stack_pict_count == 0)
    {                
        encoder = new TiffBitmapEncoder();
        encoder.Compression = TiffCompressOption.Zip;                
    }
 }

我一直在尝试:我希望压缩(调用encoder.save(fs))在主线程之外的另一个线程中执行。

我尝试将encoder.save(fs)调用BackgroundWorker来预防性地将编码器复制到本地版本(不确定它是否有效),然后拨打电话。 我收到错误,如'调用线程无法访问此对象,因为另一个线程拥有它'

如果我使用Dispatcher.Invoke(如果我正确地做了),执行将变得非常缓慢。

我犯了一些愚蠢的错误吗?


编辑:(根据@meilke和@ user7116的建议正在进行中)

我现在在BackgroundWorker中移动了压缩器的分配和执行。虽然现在传递colorBitmap,但拥有另一个线程。我试着freeze它,但看起来不够;我仍然得到一个'调用线程无法访问此对象,因为另一个线程拥有它'

        tiffCompressorWorker = new BackgroundWorker();
        tiffCompressorWorker.DoWork += (s, a) =>
        {

            initializeTiffEncoder();
            WriteableBitmap localCopy = new WriteableBitmap((WriteableBitmap)a.Argument);
            localCopy.Freeze();
            encoder.Frames.Add(BitmapFrame.Create(localCopy));

            stack_pict_count++;
            if (stack_pict_count % PICT_PER_FILE == 0)
            {
                stack_pict_count = 0;                    
                try
                {
                    using (FileStream fs = new FileStream(path, FileMode.Create))
                    {
                        saving_encoder.Save(fs);
                    }
                }
                catch (IOException)
                {
                    ..
                }
            }            
        };

2 个答案:

答案 0 :(得分:2)

您必须将整个TIFF操作放入后台工作程序。然后将输入图像的副本作为参数传递给RunWorkerAsync。以下链接指向网络上提供的众多解决方案之一:Copying from BitmapSource to WritableBitmap。将该代码放入辅助方法并使用它复制映像,然后再将其保存到磁盘。

答案 1 :(得分:0)

我不是计算机科学家,但我找到了this post,其中指出:

  

WriteableBitmap继承DispatcherObject,并且只能在拥有它的调度程序线程中访问。

而且,在我看来,你正在超越DispatcherObject的权限。