using DTS.Common.Enums.DASFactory; using DTS.Common.Interface.DASFactory; using DTS.Common.Interface.StatusAndProgressBar; using DTS.Common.Utilities.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using static DTS.DASLib.Service.ServiceBase; namespace DTS.DASLib.Service.StateMachine { public class RealtimeStatusInformation : IStatusInfo { private readonly ManualResetEvent stopRealtimeEvent = new ManualResetEvent(true); //this is a wait handle that is set when we get a callback from realtime service saying it's done private readonly ManualResetEvent realtimeDoneFromService = new ManualResetEvent(false); /// /// action to take on completion of Realtime start /// public Action CompleteAction { get; set; } public void Reset() { CompleteAction = null; realtimeDoneFromService.Reset(); stopRealtimeEvent.Set(); CouldNotStartRealtime = false; } public Action SetRealtimeSampleRateAAF { get; set; } public bool CouldNotStartRealtime { get; set; } public Callback StartRealtimeCallback { get; set; } /// /// returns the Anti-Alias Filter (AAF) for the DAS in question /// this is dependent on the sample rate for the hardware and a ratio in the config file /// (RealtimeSampleRateAAFilterRatio) /// /// /// private float GetRealtimeAAFForHardware(IDASCommunication idas, double samplerate) { var param = States.Instance.Realtime.Status.RealtimeParams; if (param.SliceTurnOffAAFRealtime && DFConstantsAndEnums.SupportsTurnOffAAFRealtime(idas)) { return Common.Constants.SLICE2_NO_AAF_REALTIME_RATE; } //for now there is no additional work done if (0 == param.RealtimeSampleRateAAFilterRatio) { return Convert.ToSingle(samplerate); } return (float)samplerate / param.RealtimeSampleRateAAFilterRatio; } public bool IsInRealtime { get { return !stopRealtimeEvent.WaitOne(2, false); } } public void StopRealtime() { stopRealtimeEvent.Set(); } Task _realtimeTask; public void StartRealtime() { _realtimeTask = Task.Run(() => { var param = States.Instance.Realtime.Status.RealtimeParams; var status = States.Instance.Realtime.Status.RealtimeStatus; var global = States.Instance.Realtime.Status.GlobalStatusParameters; StartRealtime(param.UnitsToStartRealtime, param.ModuleIndices, param.UseSingleSampleMode, param.RealtimeSampleRate, param.RealtimeDelayBetweenPollsInMilliSecond, param.AllowMultipleSampleRealtime, status.SetRealtimeSampleRateAAF, status.CompleteAction, param.IdasToActiveChannels, status.StartRealtimeCallback); }); } public void StartRealtime(List ldas, List moduleArrayIndicies, bool useSingleSampleMode, double realtimeSampleRate, int realtimeDelayBetweenPolls, bool allowMultipleSampleRealtime, Action SetRealtimeSampleRateAAF, Action CompleteAction, Dictionary idasToActiveChannels, Callback StartRealtimeCallback ) { var startRealtimeCallback = new Callback(StartRealtimeCallback); startRealtimeCallback += (data) => { if (data.Status == CallbackData.CallbackStatus.AllFinished) { //service is done, mark it realtimeDoneFromService.Set(); } if (data.Status == CallbackData.CallbackStatus.Failure) { } }; stopRealtimeEvent.Reset(); using (var realtimeService = new RealtimeService()) { try { if (ldas.Count > 0) { if (useSingleSampleMode) { realtimeDoneFromService.Reset(); realtimeService.StartActivePolling(ldas, startRealtimeCallback, ldas, stopRealtimeEvent, idasToActiveChannels); SetRealtimeSampleRateAAF(double.NaN, double.NaN); } else { realtimeDoneFromService.Reset(); realtimeService.Start(ldas, Convert.ToInt32(realtimeSampleRate), realtimeDelayBetweenPolls, startRealtimeCallback, ldas, allowMultipleSampleRealtime, moduleArrayIndicies.ToArray(), stopRealtimeEvent, idasToActiveChannels, GetRealtimeAAFForHardware); if (ldas.Any()) { SetRealtimeSampleRateAAF(realtimeSampleRate, GetRealtimeAAFForHardware(ldas[0], realtimeSampleRate)); } else { SetRealtimeSampleRateAAF(double.NaN, double.NaN); } } } } catch (Exception ex) { APILogger.Log(ex); CouldNotStartRealtime = true; //there was an exception , stop the realtime and service stopRealtimeEvent.Set(); realtimeDoneFromService.Set(); } finally { CompleteAction(); } var mr = new ManualResetEvent(false); realtimeService.ServiceAvailable += delegate { realtimeService.ServiceAvailable -= delegate { }; mr.Set(); }; while (!stopRealtimeEvent.WaitOne(30, false) && !mr.WaitOne(1, false)) { Thread.Sleep(1); } //either realtime event was signalled to stop (datapro) or the service actually did already stop //go and set the event handle to stopped to notify service in case it's running stopRealtimeEvent.Set(); //now wait for the event from the service saying it's stopped realtimeDoneFromService.WaitOne(); } } } }