2014-10-30 28 views
0

我使用kinect v2流来显示彩色图像和身体图像。 现在我想保存彩色图像,但如果我在主线程中添加代码,我不会显示任何内容,因为在硬盘上每秒写入30个文件。 所以我必须想使用线程,特别是线程池,但我有框架例外:C#使用ThreadPool将文件写入硬盘的线程

ColorCameraSettings 'colorFrame.ColorCameraSettings' ha generato un'eccezione di tipo 'System.ObjectDisposedException' Microsoft.Kinect.ColorCameraSettings {System.ObjectDisposedException} 

这是我的代码:

private void Reader_MultiSourceFrameArrived(object sender, MultiSourceFrameArrivedEventArgs e) 
    { 
     var reference = e.FrameReference.AcquireFrame(); 
     this.StatusText = "NO BODY"; 

     frameCount++; 
     //Console.WriteLine(frameCount); 
     bool dataReceived = false; 
     //sw.WriteLine("frame nuovo"); 
     using (ColorFrame frame = reference.ColorFrameReference.AcquireFrame()) 
     { 
      if (frame != null) 
      { 

       //image.Source = ToBitmap(frame); 
       ThreadPool.QueueUserWorkItem(writeColorImage, frame); 


      } 
     }.............. 

,并写:

private void writeColorImage(Object frame) 
    { 
     ColorFrame colorFrame = (ColorFrame)frame; 
     var encoder = new PngBitmapEncoder(); 
     encoder.Frames.Add(BitmapFrame.Create(ToBitmap(colorFrame))); 
     using (var filestream = new FileStream(filelocation + "image" + frameCount + ".jpg", FileMode.Create)) 
      encoder.Save(filestream); 
    } 
    private BitmapSource ToBitmap(ColorFrame frame) 
    { 
     int width = frame.FrameDescription.Width; 
     int height = frame.FrameDescription.Height; 
     PixelFormat format = PixelFormats.Bgr32; 

     byte[] pixels = new byte[width * height * ((PixelFormats.Bgr32.BitsPerPixel + 7)/8)]; 

     if (frame.RawColorImageFormat == ColorImageFormat.Bgra) 
     { 
      frame.CopyRawFrameDataToArray(pixels); 
     } 
     else 
     { 
      frame.CopyConvertedFrameDataToArray(pixels, ColorImageFormat.Bgra); 
     } 

     int stride = width * format.BitsPerPixel/8; 

     return BitmapSource.Create(width, height, 96, 96, format, null, pixels, stride); 
    } 

如何可以在硬盘上写这张图片吗?谢谢

回答

1

using语句调用Dispose on yo你的帧变量;但是,正在运行保存到磁盘的线程仍在使用对其的引用。这就是你得到这个例外的原因。此代码更改:

using (ColorFrame frame = reference.ColorFrameReference.AcquireFrame()) 
    { 
     if (frame != null) 
     { 
      //image.Source = ToBitmap(frame); 
      ThreadPool.QueueUserWorkItem(writeColorImage, frame); 
     } 
    } 

这样:

var frame = reference.ColorFrameReference.AcquireFrame(); 
    if (frame != null) 
    { 
     //image.Source = ToBitmap(frame); 
     ThreadPool.QueueUserWorkItem(writeColorImage, frame); 
    } 

,然后在writeColorImage帧调用Dispose();更改方法是这样的:

private void writeColorImage(Object frame) 
    { 
     var colorFrame = (ColorFrame) frame; 
     var encoder = new PngBitmapEncoder(); 
     encoder.Frames.Add(BitmapFrame.Create(ToBitmap(colorFrame))); 
     using (var filestream = new FileStream(filelocation + "image" + frameCount + ".jpg", FileMode.Create)) 
     { 
      encoder.Save(filestream); 
     } 
     colorFrame.Dispose(); 
    } 
+0

错误,对象不具备这种方法 – luca 2014-10-30 14:08:00

+0

@luca对不起,本来应该colorFrame,我编辑它。 – 2014-10-30 14:09:41

+0

好吧,但原来的框架?不处理? – luca 2014-10-30 14:11:38

1

您刚刚在线程池上开始您的作业之后才处置该帧。你应该在工作结束时处理它。

在事件处理Reader_MultiSourceFrameArrived取出使用,则:与frame.Dispose发生

private void writeColorImage(Object frame) 
    { 
     using (ColorFrame colorFrame = (ColorFrame)frame) 
     { 
      var encoder = new PngBitmapEncoder(); 
      encoder.Frames.Add(BitmapFrame.Create(ToBitmap(colorFrame))); 
      using (var filestream = new FileStream(filelocation + "image" + frameCount + ".jpg", FileMode.Create)) 
       encoder.Save(filestream); 
     } 
    } 
+0

如果使用using语句来对照在using语句之外创建的对象,那么using语句是否有任何指导原则?我从来没有见过它像以前那样使用,当通过在using语句中创建using语句的范围来创建对象时,始终使用它。说实话,我不知道有可能像你在示例代码中那样做,但我不确定我喜欢它! :) – 2014-10-30 13:35:41

+0

我的测试表明C#似乎没有把处理外部创建的对象传递给'using'块的问题。 MSDN指出:“您可以实例化资源对象,然后将该变量传递给using语句,但这不是最佳做法。在这种情况下,在控制离开使用块后,对象仍然在范围内,即使它可能不再有权访问其非托管资源。“在这种情况下,我认为,因为替代方案根本就不是“使用”模块,所以这可能是规则的一个例外。也许,最好有一个“使用”比不。 – BlueMonkMN 2014-10-30 13:53:05

+0

最好尽快使用。在这里你不能做其他事情(你可以使用异步,但最终结果是一样的)。这很好,因为你的任务将开始(Acquire和QueueUserWorkItem之间没有代码)并且任务的第一行是'using'。即使之前出现问题,GC/Finalizer也会处理它。如果你不喜欢使用关键字,你可以添加一个try ...最后显式的'Dispose'。 – Guillaume 2014-10-30 14:01:27

相关问题