我们使用Kinect来流用户的可定制视频,允许您在不停止流的情况下选择流类型(颜色、深度,两者都可以显示跟踪的骨架)。
如果更改流类型,我们的程序运行良好,但在启用了一些框架(仅在某些PC机上)之后,应用程序崩溃,显示:
Unhandled Exception: System.AccessViolationException.这是我们的代码:
private void KinectAllFramesReady(object sender, AllFramesReadyEventArgs e)
{
using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
currentSkeleton = GetSkeletonFromSkeletonFrame(skeletonFrame);
if (this.frameMode == Constants.VIDEO_DEPTH_MODE)
currentFrame = GetByteArrayFromDepthFrame(e);
else if (this.frameMode == Constants.VIDEO_COLOR_MODE)
currentFrame = GetByteArrayFromColorFrame(e);
else if (this.frameMode == Constants.VIDEO_NONE_MODE)
currentFrame = GetByteFromBlankFrame();
if (isSkeleton)
{
currentFrame = OverlapSkeleton(currentFrame, this.currentSkeleton);
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private byte[] OverlapSkeleton(byte[] currentFrame, Skeleton S)
{
Bitmap tempBitmap = new Bitmap(Constants.KINECT_DEFAULT_CAPTURE_WIDTH, Constants.KINECT_DEFAULT_CAPTURE_HEIGHT, PixelFormat.Format32bppArgb);
BitmapData tempBmapData = tempBitmap.LockBits(new Rectangle(0, 0, Constants.KINECT_DEFAULT_CAPTURE_WIDTH, Constants.KINECT_DEFAULT_CAPTURE_HEIGHT), ImageLockMode.ReadWrite, tempBitmap.PixelFormat);
IntPtr ptr = tempBmapData.Scan0;
for (int i = 0, offset = 0; i < Constants.KINECT_DEFAULT_CAPTURE_HEIGHT; i++)
{
Marshal.Copy(currentFrame, offset, ptr, Constants.KINECT_DEFAULT_CAPTURE_WIDTH << 2);
offset += Constants.KINECT_DEFAULT_CAPTURE_WIDTH << 2;
ptr += tempBmapData.Stride;
}
tempBitmap.UnlockBits(tempBmapData);
Graphics g = Graphics.FromImage(tempBitmap);
// Upper Body
DrawBone(JointType.Head, JointType.ShoulderCenter, S, g);
DrawBone(JointType.ShoulderCenter, JointType.Spine, S, g);
DrawBone(JointType.Spine, JointType.HipCenter, S, g);
// Left Arm
DrawBone(JointType.ShoulderCenter, JointType.ShoulderLeft, S, g);
DrawBone(JointType.ShoulderLeft, JointType.ElbowLeft, S, g);
DrawBone(JointType.ElbowLeft, JointType.WristLeft, S, g);
DrawBone(JointType.WristLeft, JointType.HandLeft, S, g);
// Right Arm
DrawBone(JointType.ShoulderCenter, JointType.ShoulderRight, S, g);
DrawBone(JointType.ShoulderRight, JointType.ElbowRight, S, g);
DrawBone(JointType.ElbowRight, JointType.WristRight, S, g);
DrawBone(JointType.WristRight, JointType.HandRight, S, g);
// Left leg
DrawBone(JointType.HipCenter, JointType.HipLeft, S, g);
DrawBone(JointType.HipLeft, JointType.KneeLeft, S, g);
DrawBone(JointType.KneeLeft, JointType.AnkleLeft, S, g);
DrawBone(JointType.AnkleLeft, JointType.FootLeft, S, g);
// Right Leg
DrawBone(JointType.HipCenter, JointType.HipRight, S, g);
DrawBone(JointType.HipRight, JointType.KneeRight, S, g);
DrawBone(JointType.KneeRight, JointType.AnkleRight, S, g);
DrawBone(JointType.AnkleRight, JointType.FootRight, S, g);
byte[] bytes = new byte[Constants.KINECT_COLOR_FRAME_SIZE];
Marshal.Copy(tempBmapData.Scan0, bytes, 0, Constants.KINECT_COLOR_FRAME_SIZE);
return bytes;
}
Constants.KINECT_COLOR_FRAME_SIZE = 1228800;
Constants.KINECT_DEFAULT_CAPTURE_WIDTH = 640;
Constants.KINECT_DEFAULT_CAPTURE_HEIGHT = 480;异常将抛出在Marshal.Copy()行。我们在这里已经看到了,所以有人建议不要一次复制整个数据块,而是循环并复制图像的每一行(参见OverlapSkeleton中的循环),但它不起作用。
奇怪的是,在我们的开发机器(i5-2410m@2.30GHz/4Gb RAM和i5-m560@2.67GHz/4Gb RAM)上,它都正常工作,但是在承载应用程序的机器上(i3-2377m@1.5GHz/4Gb RAM),在启用骨架后2-3秒后就会崩溃,抛出这个异常。
操作系统是Win7 SP1,.NET Framework4.5适用于每台机器。
知道什么会导致这个看似随机的异常吗?
发布于 2014-01-27 15:35:18
这不是真正的解决方案,但更多的是黑客/工作。
无论如何,我发现异常是随机抛出的,但并不频繁,因此解决方法是用
[HandleProcessCorruptedStateExceptions]和
[SecurityCritical]这样做,就可以使用try/catch捕获CSE。由此产生的代码是:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
private byte[] OverlapSkeleton(byte[] currentFrame, Skeleton S)
{
if (S == null)
return currentFrame;
try
{
//The above code with Marshall.copy and lines drawing
}
catch(Exception)
{
return currentFrame;
}同样,它不能解决问题,但由于没有性能影响,而且我们也没有想法,这是我必须提供的最好的解决方案。如果任何人有一个更好的/工作的想法是受欢迎的。
https://stackoverflow.com/questions/21379695
复制相似问题