清理方法中出现意外的“无法访问已处置的对象”

当我关闭我的WPF应用程序时,我正面临一个令人费解的处理对象问题。 如果你发现我的逻辑中有任何错误,请指出它们。

我有一个带有update()方法的ColorManager类,如下所示。

 public void Update(ColorImageFrame frame) { byte[] pixelData = new byte[frame.PixelDataLength]; frame.CopyPixelDataTo(pixelData); if (Bitmap == null) { Bitmap = new WriteableBitmap(frame.Width, frame.Height, 96, 96, PixelFormats.Bgr32, null); } // draw bitmap RaisePropertyChanged(() => Bitmap); } 

我在一个单独的线程中运行此方法。 在我的MainWindow.xaml.cs我有以下内容:

  private void Initialise() { if (kinectSensor == null) return; // start kinect sensor kinectSensor.Start(); updateColourStreamThread = new Thread(new ThreadStart(colorStreamDisplay)); updateColourStreamThread.Name = "updateColourStreamThread"; updateColourStreamThread.Start(); // ...some more codes } void colorStreamDisplay() { while(isDisplayActive) { using (var frame = kinectSensor.ColorStream.OpenNextFrame(500)) { if (frame == null) continue; if (displayDepthStream) continue; Dispatcher.Invoke(new Action(() => colorManager.Update(frame))); } } } 

我在MainWindow.xaml.cs有以下方法在单击关闭按钮后进行清理。

  private void Clean() { isDisplayActive = false; // some other codes if (kinectSensor != null) { updateColourStreamThread.Abort(); updateDepthStreamThread.Abort(); updateSkeletonStreamThread.Abort(); kinectSensor.Stop(); kinectSensor = null; Console.WriteLine("Closed successfully"); } 

我的应用程序在frame.CopyPixelDataTo(pixelData);上抛出“无法访问已处置的对象” frame.CopyPixelDataTo(pixelData); 点击关闭按钮后。

我将bool值切换为false以停止循环,然后我中止线程,并停止kinect设备。

我错过了什么?

当您将布尔值设置为false时,应用程序将退出while循环:

1)将你的bool设置为false

  isDisplayActive = false; 

2)将退出此循环:

  while(isDisplayActive) { using (var frame = kinectSensor.ColorStream.OpenNextFrame(500)) { if (frame == null) continue; if (displayDepthStream) continue; Dispatcher.Invoke(new Action(() => colorManager.Update(frame))); } } 

3)所以你的框架也会超出范围。 因此它将被处置……

 using (var frame = kinectSensor.ColorStream.OpenNextFrame(500)) 

4)虽然你的主线程还没有执行Thread.Abort

5)因此,您的CopyPixelDataTo将在已经处置的frame对象上执行。

 frame.CopyPixelDataTo(pixelData); 

6)和kaboom,你的对象处理exception。


Thread.Abort是个坏主意。

你永远不知道执行线程在执行之前有多远 ,这可能导致各种令人讨厌的副作用。 在此问答中阅读更多内容: 使用Thread.Abort()有什么问题

在你的情况下我会做的是替换

 while(isDisplayActive) 

有类似的东西

 while(colorThingyThreadIsBusy) 

Thread准备好(=完成处理)时,将colorThingyThreadBusy bool设置为false。

为了优雅地关闭你的应用程序,我实现了CancellationToken而不是中止线程。