2

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

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

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);单击关闭按钮后,我的应用程序抛出“无法访问已处理的对象” 。

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

我错过了什么?

4

1 回答 1

4

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

1)设置你bool为假

        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,你有你的对象处理异常。


Thread.Abort 是个坏主意。

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

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

while(isDisplayActive)

有类似的东西

while(colorThingyThreadIsBusy)

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

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

于 2013-02-18T20:44:15.520 回答