using System; using Emgu.CV; using Emgu.CV.Structure; using System.Timers; using System.Threading; using System.Diagnostics; using System.Runtime.ExceptionServices; using System.Threading.Tasks; namespace BBIWARG.Input.InputProviding { class InputProviderIntel : MarshalByRefObject, IInputProvider { IntelCameraWrapper wrapper; public int CurrentFrameID { get; set; } public float FieldOfViewHorizontal { get; set; } public float FieldOfViewVertical { get; set; } public int ImageWidth { get { return 640; } } public int ImageHeight { get { return 480; } } public bool IsActive { get; set; } public event DeviceStartedEventHandler DeviceStartedEvent; public event NewFrameEventHandler NewFrameEvent; public UInt16 lowConfidenceValue; private AppDomain domain; private System.Threading.Timer watchdogTimer; public void initialize() { CurrentFrameID = 0; watchdogTimer = new System.Threading.Timer(Timer_Elapsed, null, 2000, 1000); } private bool errorstate = false; private void Timer_Elapsed(object state) { checkExitErrorstate(); errorstate = true; } int startId = 0; Stopwatch startTimeWatch; [HandleProcessCorruptedStateExceptions] public void start() { startTimeWatch = Stopwatch.StartNew(); Console.WriteLine("starting new AppDomain (" + startId +")..."); domain = System.AppDomain.CreateDomain("AppDomain-" + startId); startId++; Task startTask = null; bool errorDuringInit = false; try { wrapper = (IntelCameraWrapper)domain.CreateInstanceAndUnwrap(typeof(IntelCameraWrapper).Assembly.GetName().ToString(), typeof(IntelCameraWrapper).FullName); startTask = Task.Run(() => wrapper.init(this)); errorDuringInit = startTask.Wait(TimeSpan.FromSeconds(4)); } catch (Exception) { Console.WriteLine("Camera crashed while init"); errorstate = true; scheduledForRestart = false; errorDuringInit = true; } if (errorDuringInit) { Console.WriteLine("Timeout during init"); errorstate = true; scheduledForRestart = false; } else { IsActive = true; if (DeviceStartedEvent != null) { DeviceStartedEvent(this, new EventArgs()); DeviceStartedEvent = null; //only notify once... } scheduledForRestart = false; try { if(!errorDuringInit) wrapper.run(); } catch (System.AccessViolationException) { Console.WriteLine("Camera caused corrupted process state."); errorstate = true; } catch (Exception) { Console.WriteLine("Camera Thread crashed."); errorstate = true; } } checkExitErrorstate(); } private bool scheduledForRestart = false; private void checkExitErrorstate() { if (errorstate && !scheduledForRestart) { if (startTimeWatch != null && startTimeWatch.ElapsedMilliseconds < 5000) { Console.WriteLine("..."); return; } //startTimeWatch.Stop(); //we have crashed. Kill the app domain and try again. Console.WriteLine("Killing AppDomain (" + domain.FriendlyName + ")..."); scheduledForRestart = true; //wrapper.terminated = true; try { System.AppDomain.Unload(domain); } catch (Exception) { Console.WriteLine("Could not unload app domain. We will just wait a moment and try to start a new one."); } domain = null; wrapper = null; Thread.Sleep(5000); start(); } } public void stop() { IsActive = false; } internal bool hasNewFrameEvent() { return NewFrameEvent != null; } internal void newFrame(int currentFrameID, Image dImg) { errorstate = false; if (startTimeWatch != null) { Console.WriteLine("done"); startTimeWatch.Stop(); startTimeWatch = null; } NewFrameEvent(this, new NewFrameEventArgs(currentFrameID, dImg)); } } }