Я занимаюсь разработкой приложения службы окна, которое обнаруживает устройства 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
}
}