private bool disposedValue = false; // To detect redundant calls protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { for (int i = 0; i < simulatorHistory.Count; i++) { this.simulatorHistory[i] = null; } this.cySimulator = null; this.cyCodeTab = null; } // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below. // TODO: set large fields to null. disposedValue = true; } }
/// <summary> /// Run the simulations asynchronously /// </summary> /// <param name="parameters">Simulation parameters</param> /// <param name="numCycles">Number of cycles to simulate</param> /// <param name="progress">Progress report update object</param> /// <param name="cancellationToken">Cancellation token for UI</param> /// <param name="inputSequence">List of globals to set at specifiec cycle numbers</param> /// <param name="cyCodeTab">CyCodeTab instance</param> /// <param name="containerPx">Bounding box of diagram container</param> /// <param name="dpiX">DPI of system - x</param> /// <param name="dpiY">DPI of system - y</param> /// <returns></returns> public Task <DFBState> RunDFBSimulations( CyParameters parameters, int numCycles, IProgress <SimProgressReport> progress, CancellationToken cancellationToken, List <InputSequence> inputSequence, CyCodeTab cyCodeTab, Rectangle containerPx, float dpiX, float dpiY) { var progressReport = new SimProgressReport(); this.inputSequence = inputSequence; stepsRequested = numCycles; cyParameters = parameters; // CyCodeTab must be instantiated on the WInForms side, with references to // UIFramework.Product4.WinForms and UIFramework.Product6.WinForms this.cyCodeTab = cyCodeTab; Assemble(); // Create state view manager var dfbState = new DFBState(this, DFBValueFormat.q23Decimal); // Return on error var errors = cyDfbAsm.Errors.GetFullList(); if (errors.Where(x => x.Type == CyMessageType.Error).Count() > 0) { return(Task.Run(() => { return dfbState; })); } // Check pending async cancel if (cancellationToken.IsCancellationRequested == true) { return(Task.Run(() => { return dfbState; })); } // Execute the simulation steps with status reports return(Task.Run(() => { // Execute DFB simulator for all cycles while (true) { bool sim; sim = SimulateStep(); if (sim && stepsExecuted < numCycles) { stepsExecuted++; } else { break; } } progressReport.TotalSteps = simulatorHistory.Count; // Generate state frames in batches if (batchSize > simulatorHistory.Count) { batchSize = simulatorHistory.Count; } var batchStartIdx = 0; var batchEndIdx = batchStartIdx + batchSize; var framesTmp = new Dictionary <int, DFBStateFrame>(); while (true) { // Check pending async cancel if (cancellationToken.IsCancellationRequested == true) { progressReport.Cancelled = true; progress.Report(progressReport); return dfbState; } // Generate a batch of frames framesTmp.Clear(); var curBatch = batchStartIdx; Parallel.For(batchStartIdx, batchEndIdx, b => { framesTmp.Add(b, DFBState.GenerateFrame(this, b, containerPx, dpiX, dpiY)); curBatch++; progressReport.CurrentStep = curBatch; progress.Report(progressReport); }); dfbState.StateFrames.AddRange(framesTmp .OrderBy(x => x.Key) .Select(x => x.Value)); batchStartIdx = batchStartIdx + batchSize; if (batchStartIdx > simulatorHistory.Count - 1) { // Last batch finished all frames break; } batchEndIdx = batchEndIdx + batchSize; // Note that batchEndIdx is exclusive in Parallel.For() if (batchEndIdx > simulatorHistory.Count) { batchEndIdx = simulatorHistory.Count; } } return dfbState; })); }