2012-01-06 16 views
0

我正在開發一個窗口服務應用程序,它檢測系統附帶的kinect設備並呈現數據。我正在使用Microsfot SDK for kinect。至於在運行應用程序之前設備已經連接,它工作正常。但是當我從系統中提取設備或者在我的應用程序正在運行時將設備附加到系統中時,我找不到未處理的對象引用異常。該應用程序的堆棧跟蹤如下當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類的實例並調用其啓動方法,則將啓動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 
    } 
} 
+0

顯示發生異常的代碼。 – 2012-01-06 09:45:36

+0

@juergend我已經添加了代碼,請參閱 – Waqar 2012-01-06 11:35:36

+0

這可能是一個錯誤。有一個MS Kinect論壇,你可以問這個問題。也許您可以聯繫Kinect開發人員:http://social.msdn.microsoft.com/Forums/en-US/kinectsdknuiapi/ – 2012-01-06 11:40:55

回答

0

我已經運行了你的代碼,我得到了你正在得到的確切錯誤。顯然,Kinect SDK是預發佈軟件,除了將代碼放入try-catch塊之外,目前沒有什麼可以做的。

我也在尋找本地庫,我認爲如果你想要做的只是檢測開/關階段,你應該將你的代碼移植到C++或者等待最後的二進制文件出來。 C++爲您提供了更多的靈活性。

祝你好運!

相關問題