Ссылка на объект не установлена ​​на экземпляр исключения объекта, когда устройство Kinect подключено или удалено - PullRequest
0 голосов
/ 06 января 2012

Я занимаюсь разработкой приложения службы окна, которое обнаруживает устройства 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 успешно обнаружит это событие и никогда не будет аварийно завершать работу.Но если регистрация события StatusChanged в методе Start закомментирована и зарегистрировать это событие в потоке обнаружения устройств 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 голосов
/ 06 января 2012

Я запустил ваш код и получаю именно ту ошибку, которую вы получаете.Очевидно, что Kinect SDK является предварительной версией программного обеспечения, и на данный момент вы ничего не можете сделать, кроме как поместить код в блок try-catch.

Я также искал нативные библиотеки и думаю, что всеВы хотите определить этапы включения / выключения, вам следует либо перенести код на C ++, либо дождаться выхода финальных двоичных файлов.C ++ дает вам больше гибкости.

Удачи!

...