意外"无法访问已释放的对象"在清理方法 [英] Unexpected "Cannot access a disposed object" in clean up method
问题描述
我现在面临一个令人费解的释放的对象问题,当我关闭我的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.
这篇关于意外"无法访问已释放的对象"在清理方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!