意外"无法访问已释放的对象"在清理方法 [英] Unexpected "Cannot access a disposed object" in clean up method

查看:166
本文介绍了意外"无法访问已释放的对象"在清理方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在面临一个令人费解的释放的对象问题,当我关闭我的WPF应用程序。如果你在我的逻辑发现任何错误,请指出来。



我有一个颜色管理软件更新()方法,如下图所示。

 公共无效更新(ColorImageFrame帧)
{
的byte [] PixelData取出=新的字节[frame.PixelDataLength]

frame.CopyPixelDataTo(PixelData取出);

如果(位图== NULL)
{
位图=新的WriteableBitmap的(frame.Width,
frame.Height,
96,
96,
PixelFormats.Bgr32,
NULL);
}
//画出位

RaisePropertyChanged(()=>位图);
}



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

 私人无效初始化()
{
如果(kinectSensor == NULL)
的回报;
//启动Kinect感应器
kinectSensor.Start();

updateColourStreamThread =新主题(新的ThreadStart(colorStreamDisplay));
updateColourStreamThread.Name =updateColourStreamThread;
updateColourStreamThread.Start();

// ...一些代码
}

无效colorStreamDisplay()
{
,而(isDisplayActive)
{使用(VAR帧= kinectSensor.ColorStream.OpenNextFrame(500))
{
如果(帧== NULL)继续
;

如果(displayDepthStream)继续;

Dispatcher.Invoke(新动作(()=> colorManager.Update(帧)));
}
}
}



我有以下方法 MainWindow.xaml.cs 做清理点击关闭按钮后。

 私人无效清除()
{
isDisplayActive = FALSE;
//其它一些代码

如果(kinectSensor!= NULL)
{
updateColourStreamThread.Abort();
updateDepthStreamThread.Abort();
updateSkeletonStreamThread.Abort();

kinectSensor.Stop();
kinectSensor = NULL;
Console.WriteLine(胜利闭幕);
}



我的应用程序将引发对 frame.CopyPixelDataTo(PixelData取出); 后,我点击关闭按钮。



我bool值切换为false停止循环,然后我放弃线程,并停止Kinect的设备。



我错过了什么?


解决方案

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



1)设置你的布尔为false

  isDisplayActive = FALSE; 



2)将退出此循环:



<$而(isDisplayActive)
{
使用(VAR帧= kinectSensor.ColorStream.OpenNextFrame(500))
{
$ p p> 如果(帧= = NULL)继续;
如果(displayDepthStream)继续;

Dispatcher.Invoke(新动作(()=> colorManager.Update(帧)));
}
}



3)因此,你的框架将走出去的范围太。因此它将被处置...

 使用(VAR帧= kinectSensor.ColorStream.OpenNextFrame(500))

4)当你的主线程还没有执行 Thread.Abort的呢。



5),因此,你的 CopyPixelDataTo 将在一个已经部署了<$ C $执行C>架对象

  frame.CopyPixelDataTo(PixelData取出)。 



6)和KABOOM,你有你的对象处理异常。






Thread.Abort的是一个坏主意。



您永远不知道的多远执行线程是它得到了执行前,这可能会导致各种讨厌的副作用。更多在这个Q&安培; A:这有什么错用Thread.Abort的()



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

 而(isDisplayActive)

喜欢的东西。

 而(colorThingyThreadIsBusy)

和设置 colorThingyThreadBusy 布尔当你的准备好假(=进行处理)。



为了优雅地关闭应用程序我想实现一个的CancellationToken 而非中止线程。


I am facing a puzzling disposed object issue when I shut down my WPF application. If you spot any mistakes in my logic please point them out.

I have a ColorManager class with update() method, as shown below.

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);   
}

I run this method in a separate thread. In my MainWindow.xaml.cs I have the following:

    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)));
                }
            }
        }

I have the following method in MainWindow.xaml.cs to do the clean up after clicking the close button.

    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");
        }

My application throws "cannot access a disposed object" on frame.CopyPixelDataTo(pixelData); after I click the close button.

I switch the bool value to false to stop the loop, then I abort the thread, and stop the kinect device.

What did I miss?

解决方案

When you set your boolean to false, the application will exit the while loop:

1) Setting your bool to false

        isDisplayActive = false;

2) will exit this loop:

        while(isDisplayActive)
        {
            using (var frame = kinectSensor.ColorStream.OpenNextFrame(500))
            {
                if (frame == null) continue;
                if (displayDepthStream) continue;

                Dispatcher.Invoke(new Action(() => colorManager.Update(frame)));
            }
        }

3) So your frame will go out of scope too. Consequently it will be disposed...

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

4) While your main thread did not yet execute the Thread.Abort yet.

5) And thus, your CopyPixelDataTo will be executed on an already disposed frame object.

frame.CopyPixelDataTo(pixelData);

6) And kaboom, you have your object disposed exception.


Thread.Abort is a bad idea.

You never know how far the executing thread was before it got executed, which can lead to all kinds of nasty side effects. Read more in this Q&A: What's wrong with using Thread.Abort()

What I would do in your situation is replace the

while(isDisplayActive)

with something like

while(colorThingyThreadIsBusy)

And set the colorThingyThreadBusy bool to false when your Thread is ready (=done processing).

In order to gracefully close your application I'd implement a CancellationToken instead of aborting Threads.

这篇关于意外&QUOT;无法访问已释放的对象&QUOT;在清理方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆