diff --git a/VectoCore/VectoCore/Models/Simulation/Impl/JobContainer.cs b/VectoCore/VectoCore/Models/Simulation/Impl/JobContainer.cs index 775c19f5ccd8861a42cccb59e153412c68f7a446..39f257b9139e565522136b35194128c4ac6aa2d0 100644 --- a/VectoCore/VectoCore/Models/Simulation/Impl/JobContainer.cs +++ b/VectoCore/VectoCore/Models/Simulation/Impl/JobContainer.cs @@ -29,203 +29,205 @@ * Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology */ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using TUGraz.VectoCommon.Models; -using TUGraz.VectoCore.Models.SimulationComponent.Data; -using TUGraz.VectoCore.OutputData; - -namespace TUGraz.VectoCore.Models.Simulation.Impl -{ - /// <summary> - /// Container for simulation jobs. - /// </summary> - public class JobContainer : LoggingObject - { - internal readonly List<RunEntry> Runs = new List<RunEntry>(); - private readonly SummaryDataContainer _sumWriter; - - private static int _jobNumber; - - /// <summary> - /// Initializes a new empty instance of the <see cref="JobContainer"/> class. - /// </summary> - /// <param name="sumWriter">The sum writer.</param> - public JobContainer(SummaryDataContainer sumWriter) - { - _sumWriter = sumWriter; - } - - public void AddRun(IVectoRun run) - { - Interlocked.Increment(ref _jobNumber); - Runs.Add(new RunEntry { Run = run, JobContainer = this }); - } - - public struct CycleTypeDescription - { - public string Name; - public CycleType CycleType; - } - - public IEnumerable<CycleTypeDescription> GetCycleTypes() - { - return - Runs.Select( - r => new CycleTypeDescription { Name = r.Run.CycleName, CycleType = r.Run.GetContainer().RunData.Cycle.CycleType }) - .Distinct(); - } - - /// <summary> - /// Adds the runs from the factory to the job container. - /// </summary> - /// <returns>A List of Run-Identifiers (unique), int</returns> - public List<int> AddRuns(SimulatorFactory factory) - { - var runIDs = new List<int>(); - - factory.SumData = _sumWriter; - factory.JobNumber = Interlocked.Increment(ref _jobNumber); - - foreach (var run in factory.SimulationRuns()) { - var entry = new RunEntry { Run = run, JobContainer = this }; - Runs.Add(entry); - runIDs.Add(entry.Run.RunIdentifier); - } - return runIDs; - } - - /// <summary> - /// Execute all runs, waits until finished. - /// </summary> - public void Execute(bool multithreaded = true) - { - Log.Info("VectoRun started running. Executing Runs."); - if (multithreaded) { - Runs.ForEach(r => r.RunWorkerAsync()); - } else { - var first = new Task(() => { }); - var task = first; - // ReSharper disable once LoopCanBeConvertedToQuery - foreach (var run in Runs) { - var r = run; - task = task.ContinueWith(t => r.RunWorkerAsync().Wait(), TaskContinuationOptions.OnlyOnRanToCompletion); - } - first.Start(); - } - } - - public void Cancel() - { - foreach (var job in Runs) { - job.CancelAsync(); - } - WaitFinished(); - } - - public void CancelCurrent() - { - foreach (var job in Runs) { - job.CancelAsync(); - } - } - - public void WaitFinished() - { - try { - Task.WaitAll(Runs.Select(r => r.RunTask).ToArray()); - } catch (Exception) { - // ignored - } - } - - private void JobCompleted() - { - if (AllCompleted) { - _sumWriter.Finish(); - } - } - - public bool AllCompleted - { - get { return Runs.All(r => r.Done); } - } - - public Dictionary<int, ProgressEntry> GetProgress() - { - return Runs.ToDictionary( - r => r.Run.RunIdentifier, - r => new ProgressEntry { - RunName = r.Run.RunName, - CycleName = r.Run.CycleName, - RunSuffix = r.Run.RunSuffix, - Progress = r.Run.Progress, - Done = r.Done, - ExecTime = r.ExecTime, - Success = r.Success, - Canceled = r.Canceled, - Error = r.ExecException - }); - } - - public class ProgressEntry - { - public string RunName; - public double Progress; - public double ExecTime; - public Exception Error; - public bool Canceled; - public bool Success; - public bool Done; - public string CycleName; - public string RunSuffix; - } - - [DebuggerDisplay("{Run.RunIdentifier}: {Run.RunName}, {Run.CycleName}")] - internal class RunEntry : LoggingObject - { - public IVectoRun Run; - public JobContainer JobContainer; - public bool Done; - public bool Success; - public bool Canceled; - public double ExecTime; - public Exception ExecException; - public readonly Task RunTask; - - public RunEntry() - { - RunTask = new Task(() => { - var stopWatch = Stopwatch.StartNew(); - try { - Run.Run(); - } catch (Exception ex) { - Log.Error(ex, "Error during simulation run!"); - ExecException = ex; - } - stopWatch.Stop(); - Success = Run.FinishedWithoutErrors && ExecException == null; - Done = true; - ExecTime = stopWatch.Elapsed.TotalMilliseconds; - JobContainer.JobCompleted(); - }); - } - - public Task RunWorkerAsync() - { - RunTask.Start(); - return RunTask; - } - - public void CancelAsync() - { - Run.Cancel(); - Canceled = true; - } - } - } +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCore.Models.SimulationComponent.Data; +using TUGraz.VectoCore.OutputData; + +namespace TUGraz.VectoCore.Models.Simulation.Impl +{ + /// <summary> + /// Container for simulation jobs. + /// </summary> + public class JobContainer : LoggingObject + { + internal readonly List<RunEntry> Runs = new List<RunEntry>(); + private readonly SummaryDataContainer _sumWriter; + + private static int _jobNumber; + + /// <summary> + /// Initializes a new empty instance of the <see cref="JobContainer"/> class. + /// </summary> + /// <param name="sumWriter">The sum writer.</param> + public JobContainer(SummaryDataContainer sumWriter) + { + _sumWriter = sumWriter; + } + + public void AddRun(IVectoRun run) + { + Interlocked.Increment(ref _jobNumber); + Runs.Add(new RunEntry { Run = run, JobContainer = this }); + } + + public struct CycleTypeDescription + { + public string Name; + public CycleType CycleType; + } + + public IEnumerable<CycleTypeDescription> GetCycleTypes() + { + return + Runs.Select( + r => new CycleTypeDescription { Name = r.Run.CycleName, CycleType = r.Run.GetContainer().RunData.Cycle.CycleType }) + .Distinct(); + } + + /// <summary> + /// Adds the runs from the factory to the job container. + /// </summary> + /// <returns>A List of Run-Identifiers (unique), int</returns> + public List<int> AddRuns(SimulatorFactory factory) + { + var runIDs = new List<int>(); + + factory.SumData = _sumWriter; + factory.JobNumber = Interlocked.Increment(ref _jobNumber); + + foreach (var run in factory.SimulationRuns()) { + var entry = new RunEntry { Run = run, JobContainer = this }; + Runs.Add(entry); + runIDs.Add(entry.Run.RunIdentifier); + } + return runIDs; + } + + /// <summary> + /// Execute all runs, waits until finished. + /// </summary> + public void Execute(bool multithreaded = true) + { + Log.Info("VectoRun started running. Executing Runs."); + if (multithreaded) { + Runs.ForEach(r => r.RunWorkerAsync()); + } else { + var first = new Task(() => { }); + var task = first; + // ReSharper disable once LoopCanBeConvertedToQuery + foreach (var run in Runs) { + var r = run; + task = task.ContinueWith(t => r.RunWorkerAsync().Wait(), TaskContinuationOptions.OnlyOnRanToCompletion); + } + first.Start(); + } + } + + public void Cancel() + { + foreach (var job in Runs) { + job.CancelAsync(); + } + WaitFinished(); + } + + public void CancelCurrent() + { + foreach (var job in Runs) { + job.CancelAsync(); + } + } + + public void WaitFinished() + { + try { + Task.WaitAll(Runs.Select(r => r.RunTask).ToArray()); + } catch (Exception) { + // ignored + } + } + + [MethodImpl(MethodImplOptions.Synchronized)] + private void JobCompleted() + { + if (AllCompleted) { + _sumWriter.Finish(); + } + } + + public bool AllCompleted + { + get { return Runs.All(r => r.Done); } + } + + public Dictionary<int, ProgressEntry> GetProgress() + { + return Runs.ToDictionary( + r => r.Run.RunIdentifier, + r => new ProgressEntry { + RunName = r.Run.RunName, + CycleName = r.Run.CycleName, + RunSuffix = r.Run.RunSuffix, + Progress = r.Run.Progress, + Done = r.Done, + ExecTime = r.ExecTime, + Success = r.Success, + Canceled = r.Canceled, + Error = r.ExecException + }); + } + + public class ProgressEntry + { + public string RunName; + public double Progress; + public double ExecTime; + public Exception Error; + public bool Canceled; + public bool Success; + public bool Done; + public string CycleName; + public string RunSuffix; + } + + [DebuggerDisplay("{Run.RunIdentifier}: {Run.RunName}, {Run.CycleName}")] + internal class RunEntry : LoggingObject + { + public IVectoRun Run; + public JobContainer JobContainer; + public bool Done; + public bool Success; + public bool Canceled; + public double ExecTime; + public Exception ExecException; + public readonly Task RunTask; + + public RunEntry() + { + RunTask = new Task(() => { + var stopWatch = Stopwatch.StartNew(); + try { + Run.Run(); + } catch (Exception ex) { + Log.Error(ex, "Error during simulation run!"); + ExecException = ex; + } + stopWatch.Stop(); + Success = Run.FinishedWithoutErrors && ExecException == null; + Done = true; + ExecTime = stopWatch.Elapsed.TotalMilliseconds; + JobContainer.JobCompleted(); + }); + } + + public Task RunWorkerAsync() + { + RunTask.Start(); + return RunTask; + } + + public void CancelAsync() + { + Run.Cancel(); + Canceled = true; + } + } + } } \ No newline at end of file diff --git a/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs b/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs index 94b126fb303badf35787b2c182532e357cc9a6c2..10225212bc94339cc8e7f6b1b6c2abd1b0028e3b 100644 --- a/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs +++ b/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs @@ -283,6 +283,7 @@ namespace TUGraz.VectoCore.OutputData /// <summary> /// Finishes the summary data container (writes the data to the sumWriter). /// </summary> + [MethodImpl(MethodImplOptions.Synchronized)] public virtual void Finish() { if (_sumWriter != null) { @@ -300,8 +301,6 @@ namespace TUGraz.VectoCore.OutputData /// Writes the result of one run into the summary data container. /// </summary> [MethodImpl(MethodImplOptions.Synchronized)] - //public virtual void Write(IModalDataContainer modData, string jobFileName, string jobName, string cycleFileName, - // Kilogram vehicleMass, Kilogram vehicleLoading, CubicMeter cargoVolume, uint gearCount) public virtual void Write(IModalDataContainer modData, int jobNr, int runNr, VectoRunData runData) { var row = Table.NewRow();