附加或删除Kinect设备时,对象引用未设置为对象异常的实例

时间:2012-01-06 07:47:50

标签: c#-4.0 windows-services kinect

我正在开发一个窗口服务应用程序,它检测附带系统的kinect设备并呈现数据。我正在使用Microsfot的SDK进行kinect。至于在运行应用程序之前已经连接了设备,它可以正常工作。但是当我从系统中重新启动设备或在我的应用程序运行时将设备连接到系统时,我得到了未找到对象引用的未处理异常。该应用程序的堆栈跟踪如下

--------------------System.NullReferenceException--------------------

Object reference not set to an instance of an object.

   at Microsoft.Research.Kinect.Nui.KinectDeviceCollection.CINuiInstanceHelper_OnStatusChanged(CStatusChangedEventArgs args)

   at INuiInstanceHelper.CINuiInstanceHelper.RaiseOnStatusChanged(_NuiStatusData* pStatusArgs)

   at ?A0xc93b94dd.NuiStatusCallback(_NuiStatusData* pStatusArgs)

我还注册了'StatusChanged'事件。如果我在桌面应用程序中执行它我工作正常它检测到设备的删除和附件,但当我在窗口服务中它会给出错误。两个应用程序中的代码都相同。另外我注意到当我在桌面应用程序中的一个单独的线程(主应用程序线程除外)中注册'StatusChanged'事件时,它开始给出相同的错误。我还注册了AppDomain的'UnhandledException'事件来停止崩溃我的应用程序,但它没有停止崩溃。


Follwing是代码。如果您创建KinectManager类的实例并调用其start方法,那么将启动kinect设备检测线程。现在,如果在运行应用程序后附加或删除kinect设备,KinectManager实例将成功检测到此事件,并且永远不会崩溃。但是如果注释了Start方法中的'StatusChanged'事件注册并在Kinect设备检测线程中注册了此事件,那么在连接或删除kinect设备后运行应用程序之后会发生未处理的异常。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.Research.Kinect.Nui;
using System.Runtime.InteropServices;

namespace Kinect_Manager
{
    /// <summary>
    /// Kinect manager class
    /// </summary>
    public class KinectManager
    {
        #region DATA MEMBERS
        private readonly Object _StartSync = new Object();
        private Object _RunTimeSync = new Object();
        private AutoResetEvent stopWait;
        private Dictionary<String, Runtime> detectedRuntimes;
        private List<String> initilizedRunTimes;
        #endregion

        #region PROPERTIES
        /// <summary>
        /// Gets true if kinect manager is started, else false.
        /// </summary>
        public bool Started { get; private set; }
        #endregion

        #region CONSTRUCTOR
        /// <summary>
        /// Consructor
        /// </summary>
        public KinectManager()
        {
            this.stopWait = new AutoResetEvent(false);
            this.Started = false;
            this.detectedRuntimes = new Dictionary<String, Runtime>();
            this.initilizedRunTimes = new List<String>();

            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
        }
        #endregion

        #region PRIVATE METHODS
        /// <summary>
        /// Thread to detect any Kinect device attached and initialzes it.
        /// </summary>
        /// <param name="state">Thread state.</param>
        private void DetectKinectThread(Object state)
        {
            try
            {
                lock (this._StartSync)
                {
                    if (!this.Started) return;

                    //To raise the unhandled exception on kinect attach or detech after Start() method call uncomment following line.
                    //Runtime.Kinects.StatusChanged += new EventHandler<StatusChangedEventArgs>(Kinects_StatusChanged);
                }

                while (true)
                {
                    try
                    {
                        if (!this.Started) return;

                        foreach (Runtime runTime in Runtime.Kinects)
                        {
                            if (!this.Started) return;
                            if (this.detectedRuntimes.ContainsKey(runTime.InstanceName)) continue;

                            this.detectedRuntimes.Add(runTime.InstanceName, runTime);
                            this.InitilizeRunTime(runTime);
                        }
                    }
                    catch { }
                    finally
                    {
                        if (this.Started)
                        {
                            this.stopWait.Reset();
                            this.stopWait.WaitOne(5000);
                        }
                    }
                }
            }
            catch { }
            finally
            {
                //Runtime.Kinects.StatusChanged -= new EventHandler<StatusChangedEventArgs>(Kinects_StatusChanged);
                { try { Thread.CurrentThread.Abort(); } catch { } }//Abort current thread and ingore any exception while doing it.
            }
        }

        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { }

        private void Kinects_StatusChanged(object sender, StatusChangedEventArgs e)
        {
            try
            {
                this.InitilizeRunTime(e.KinectRuntime);
            }
            catch { }
        }

        private void KinectRuntime_VideoFrameReady(object sender, ImageFrameReadyEventArgs e) { }

        private void KinectRuntime_DepthFrameReady(object sender, ImageFrameReadyEventArgs e) { }

        private void KinectRuntime_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e) { }

        /// <summary>
        /// Initilizes the run time if status is connected.
        /// </summary>
        /// <param name="runTime">Runtime instance.</param>
        private void InitilizeRunTime(Runtime runTime)
        {
            try
            {
                Monitor.Enter(this._RunTimeSync);

                if (!this.detectedRuntimes.ContainsKey(runTime.InstanceName)) return;

                if (runTime.Status != KinectStatus.Connected)
                {
                    if (this.initilizedRunTimes.Contains(runTime.InstanceName))
                    {
                        runTime.Uninitialize();
                        this.initilizedRunTimes.Remove(runTime.InstanceName);
                    }

                    return;
                }
                else if (this.initilizedRunTimes.Contains(runTime.InstanceName)) return; //Because run time is already initilized

                RuntimeOptions runtimeOptions = RuntimeOptions.UseDepthAndPlayerIndex | RuntimeOptions.UseSkeletalTracking | RuntimeOptions.UseColor;

                runTime.Initialize(runtimeOptions);
                runTime.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color);
                runTime.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.DepthAndPlayerIndex);

                if (runtimeOptions.HasFlag(RuntimeOptions.UseSkeletalTracking))
                {
                    runTime.SkeletonEngine.TransformSmooth = true;
                    runTime.SkeletonEngine.SmoothParameters = new TransformSmoothParameters
                    {
                        Smoothing = 1.0f,
                        Correction = 0.1f,
                        Prediction = 0.1f,
                        JitterRadius = 0.05f,
                        MaxDeviationRadius = 0.05f
                    };
                }

                runTime.VideoFrameReady += new EventHandler<ImageFrameReadyEventArgs>(KinectRuntime_VideoFrameReady);
                runTime.DepthFrameReady += new EventHandler<ImageFrameReadyEventArgs>(KinectRuntime_DepthFrameReady);
                runTime.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(KinectRuntime_SkeletonFrameReady);

                this.initilizedRunTimes.Add(runTime.InstanceName);
            }
            catch (Exception exp)
            {
                { try { runTime.Uninitialize(); } catch { } } // ignore any exception

                if (this.initilizedRunTimes.Contains(runTime.InstanceName)) { this.initilizedRunTimes.Remove(runTime.InstanceName); }

                if (exp is COMException)
                {
                    COMException comException = exp as COMException;
                    if (comException.ErrorCode == -2147220947)  //Runtime is being used by another app.
                    {
                        //Log that this kinect device is used by  another app.
                        return;
                    }
                }

                //Log detail exception here.
            }
            finally { Monitor.Exit(this._RunTimeSync); }
        }
        #endregion

        #region PUBLIC METHODS
        /// <summary>
        /// Starts the kinect manager.
        /// </summary>
        public void Start()
        {
            lock (this._StartSync)
            {
                if (this.Started) return;

                this.stopWait.Reset();

                ThreadPool.QueueUserWorkItem(this.DetectKinectThread);
                this.Started = true;

                //To raise the unhandled exception on kinect attach or detech after Start() method call comment following event registration.
                //and uncomment the event registration in DetectKinectThread thread
                Runtime.Kinects.StatusChanged += new EventHandler<StatusChangedEventArgs>(Kinects_StatusChanged);
            }
        }

        /// <summary>
        /// Stops the kinect manager.
        /// </summary>
        public void Stop()
        {
            lock (this._StartSync)
            {
                this.Started = false;
                this.stopWait.Set();

                Runtime.Kinects.StatusChanged -= new EventHandler<StatusChangedEventArgs>(Kinects_StatusChanged);

                Runtime[] allRunTimes = new Runtime[this.detectedRuntimes.Count];
                this.detectedRuntimes.Values.CopyTo(allRunTimes, 0);
                this.detectedRuntimes.Clear();
                this.initilizedRunTimes.Clear();

                foreach (Runtime runTime in allRunTimes) { try { runTime.Uninitialize(); } catch { } }
            }
        }
        #endregion
    }
}

1 个答案:

答案 0 :(得分:0)

我已经运行了您的代码,我收到了您正在收到的确切错误。显然,Kinect SDK是预发布软件,目前除了将代码放在try-catch块中之外别无他法。

我也在查看本机库,我想如果你想做的就是检测开/关阶段,你应该将代码移植到C ++或者等待最终的二进制文件出来。 C ++为您提供了更大的灵活性。

祝你好运!