1

问题:如何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可以预防性地将编码器复制到本地版本的调用中(但不确定它是否有效),然后进行调用。我收到类似“调用线程无法访问此对象,因为另一个线程拥有它”之类的错误。

如果我使用 a 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)
                {
                    ..
                }
            }            
        };
4

2 回答 2

2

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

于 2013-09-13T18:42:25.283 回答
0

我不是计算机科学家,但我发现了这篇文章,其中指出:

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

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

于 2016-12-22T18:48:49.120 回答