private bool stopAndCleanupTasks() { try { bool ans = true; if (fpgaTasks != null) { foreach (FpgaTimebaseTask ftask in fpgaTasks.Values) { ftask.Stop(); if (ftask.ClockStatus == DataStructures.Timing.SoftwareClockProvider.Status.Running) ftask.AbortClockProvider(); } fpgaTasks.Clear(); } if (variableTimebaseClockTask != null) { try { variableTimebaseClockTask.Stop(); } catch (Exception e) { messageLog(this, new MessageEvent("Caught exception when trying to stop the variable timebase output task. This may indicate that the variable timebase clock suffered a buffer underrun in the previous run. Exception follows: " + e.Message + e.StackTrace)); displayError(); ans = false; } try { variableTimebaseClockTask.Dispose(); } catch (Exception e) { messageLog(this, new MessageEvent("Caught exception when trying to dispose of the variable timebase output task. This may indicate that the variable timebase clock suffered a buffer underrun in the previous run. Exception follows: " + e.Message + e.StackTrace)); displayError(); ans = false; } variableTimebaseClockTask = null; } if (daqMxTasks == null) { daqMxTasks = new Dictionary<string, Task>(); } else { List<string> stopMe = new List<string>(daqMxTasks.Keys); foreach (string dev in stopMe) { try { daqMxTasks[dev].Stop(); } catch (Exception e) { messageLog(this, new MessageEvent("Caught exception when trying to stop task on device " + dev + ". This may indicate that the previous run suffered from a buffer underrun. Exception follows: " + e.Message + e.StackTrace)); displayError(); ans = false; } try { daqMxTasks[dev].Dispose(); } catch (Exception e) { messageLog(this, new MessageEvent("Caught exception when trying to dispose of task on device " + dev + ". This may indicated that the previous run suffered from a buffer underrun. Exception follows: " + e.Message + e.StackTrace)); displayError(); ans = false; } daqMxTasks.Remove(dev); } GC.Collect(); GC.Collect(); } if (computerClockProvider != null) if (computerClockProvider.ClockStatus== DataStructures.Timing.SoftwareClockProvider.Status.Running) computerClockProvider.AbortClockProvider(); computerClockProvider = null; if (clockBroadcaster != null) clockBroadcaster = null; if (gpibTasks == null) { gpibTasks = new Dictionary<HardwareChannel, GpibTask>(); } else { gpibTasks.Clear(); } if (rs232Tasks == null) { rs232Tasks = new Dictionary<HardwareChannel, RS232Task>(); } else { rs232Tasks.Clear(); } if (rfsgTasks == null) { rfsgTasks = new Dictionary<HardwareChannel, RfsgTask>(); } else { rfsgTasks.Clear(); } // resetAllDevices(); System.GC.Collect(); System.GC.Collect(); taskErrorsDetected = false; return ans; } catch (Exception e) { messageLog(this, new MessageEvent("Caught exception when attempting to stop tasks. " + e.Message + e.StackTrace)); displayError(); return false; } }
/// <summary> /// Start hardware triggered tasks, and software triggerred tasks which run off an external sample clock. This function also /// sets up the software-timed task triggering mechanism, if one is in use. /// </summary> /// <returns></returns> public override bool armTasks(UInt32 clockID) { lock (remoteLockObj) { try { messageLog(this, new MessageEvent("Arming tasks")); int armedTasks = 0; DataStructures.Timing.SoftwareClockProvider softwareClockProvider; // chose local software clock provider... if (serverSettings.ReceiveNetworkClock) { softwareClockProvider = new DataStructures.Timing.NetworkClockProvider(clockID); messageLog(this, new MessageEvent("Using network clock as software clock provider.")); } else if (fpgaTasks!=null && fpgaTasks.Count != 0) { IEnumerator<string> e = fpgaTasks.Keys.GetEnumerator(); e.MoveNext(); string key = e.Current; softwareClockProvider = fpgaTasks[key]; messageLog(this, new MessageEvent("Using FPGA task on device " + key + " as software clock source.")); } else { if (computerClockProvider != null) { throw new Exception("Expected computer clock provider to be null when arming task. Aborting."); } this.computerClockProvider = new DataStructures.Timing.ComputerClockSoftwareClockProvider(5); softwareClockProvider = computerClockProvider; messageLog(this, new MessageEvent("Using computer clock as software clock source.")); } // create a clock broadcaster if (clockBroadcaster != null) { throw new Exception("Expected clockBroadcaster to be null when it was not."); } if (serverSettings.BroadcastNetworkClock && ! serverSettings.ReceiveNetworkClock) { clockBroadcaster = new DataStructures.Timing.NetworkClockBroadcaster(clockID, (uint)((sequence.SequenceDuration * 1000.0) + 100)); softwareClockProvider.addSubscriber(clockBroadcaster, 20); } // add software clock subscribers foreach (RfsgTask task in this.rfsgTasks.Values) softwareClockProvider.addSubscriber(task, 1); foreach (GpibTask task in this.gpibTasks.Values) softwareClockProvider.addSubscriber(task, 1); foreach (RS232Task task in this.rs232Tasks.Values) softwareClockProvider.addSubscriber(task, 1); lock (softwareTriggeringTaskLock) { softwareTriggeringTask = null; } softwareTimedTasksTriggered = false; softwareTimedTriggerCount = 0; foreach (string dev in myServerSettings.myDevicesSettings.Keys) { if (daqMxTasks.ContainsKey(dev)) { DeviceSettings ds = myServerSettings.myDevicesSettings[dev]; // Start the task if it is hardware triggered, or if it is software triggered but with an external sample clock. if ((ds.StartTriggerType == DeviceSettings.TriggerType.TriggerIn) || ((ds.StartTriggerType == DeviceSettings.TriggerType.SoftwareTrigger) && (ds.MySampleClockSource == DeviceSettings.SampleClockSource.External))) { Task task = daqMxTasks[dev]; if (dev == serverSettings.DeviceToSyncSoftwareTimedTasksTo) { if (serverSettings.SoftwareTaskTriggerMethod == ServerSettings.SoftwareTaskTriggerType.SampleClockEvent) { messageLog(this, new MessageEvent("***** You are using SampleClockEvent as your SoftwareTaskTriggerMethod (in your ServerSettings). This is not recommended and no longer supported. Use PollBufferPosition instead. *****")); displayError(); /* lock (softwareTriggeringTaskLock) { softwareTriggeringTask = task; } task.SampleClock += triggerSoftwareTimedTasks; */ return false; } } task.Start(); if (dev == serverSettings.DeviceToSyncSoftwareTimedTasksTo) { if (serverSettings.SoftwareTaskTriggerMethod == ServerSettings.SoftwareTaskTriggerType.PollBufferPosition) { if (softwareTaskTriggerPollingThread != null) { if (softwareTaskTriggerPollingThread.ThreadState == ThreadState.Running) { softwareTaskTriggerPollingThread.Abort(); if (softwareTaskTriggerPollingThread.ThreadState != ThreadState.Aborted) { throw new Exception("Unable to abort an already-running software-task triggering polling thread."); } } } lock (softwareTriggeringTaskLock) { softwareTriggeringTask = task; softwareTaskTriggerPollingFunctionInitialPosition = task.Stream.TotalSamplesGeneratedPerChannel; softwareTaskTriggerPollingThread = new Thread(new ThreadStart(softwareTaskTriggerPollingFunction)); softwareTaskTriggerPollingThread.Start(); } } } armedTasks++; } } } messageLog(this, new MessageEvent(armedTasks.ToString() + " tasks armed.")); if (variableTimebaseClockTask != null) { variableTimebaseClockTask.Control(TaskAction.Commit); } //if needed, the analog input task is launched here if (analogInCardDetected) reader_analog_S7.BeginReadMultiSample(sequence.nSamples(1 / (double)(AtticusServer.server.serverSettings.AIFrequency)), new AsyncCallback(callback_S7), null); return true; } catch (Exception e) { messageLog(this, new MessageEvent("Unable to arm tasks due to exception: " + e.Message + e.StackTrace)); displayError(); return false; } } }