/// <summary> /// Runs creates the thread with specified specified arguments and starts this thread. /// </summary> /// <param name="args">The args.</param> /// <returns>The the AutoResetEvent that will signal, when the thread finishes.</returns> public AutoResetEvent Run(RunnableNodeThreadArgs args) { if (args == null || args.ExperimentRunner == null) { throw new ArgumentNullException("args", "RunnableNodeThreadArgs and its dispatcher cannot be null to start a thread"); } args.Node = this; // Sets the state of the reset event to nonsignaled m_nodeResetEvent.Reset(); // Create a task and supply a user delegate by using a lambda expression. var nodeThread = ThreadFactory.CreateThread(new ParameterizedThreadStart(ThreadRun)); nodeThread.Name = String.Format("Worker: {0}, {1}", Id, Label); nodeThread.IsBackground = true; nodeThread.SetApartmentState(ApartmentState.STA); nodeThread.Start(args); m_nodeThread = nodeThread; return(m_nodeResetEvent); }
public bool Equals(RunnableNodeThreadArgs otherArgs) { if (otherArgs == null) throw new ArgumentNullException("otherArgs"); bool areEqual = ExperimentRunner == otherArgs.ExperimentRunner; areEqual &= Node == otherArgs.Node; return areEqual; }
private static void ThreadRun(object obj) { RunnableNodeThreadArgs args = (RunnableNodeThreadArgs)obj; RunnableNode activeNode = (RunnableNode)args.Node; //System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); // Notify that this node is starting work args.ExperimentRunner.OnNodeExecuting(activeNode); Exception error = null; try { activeNode.RunInternal(); } catch (Exception e) { error = e; } if (error != null) { activeNode.HasError = true; activeNode.ErrorMessage = error.Message; RunnableComponentNode componentNode = activeNode as RunnableComponentNode; if (componentNode != null) { if (error is ComponentException) { componentNode.Logger.Error(error.Message); } else { componentNode.Logger.ErrorException(error.Message, error); } } args.ExperimentRunner.OnNodeHasError(activeNode, activeNode.ErrorMessage); args.ExperimentRunner.TerminateExperimentExecution(); } else { // Notify this node is done, then start preparing for any remaining nodes. args.ExperimentRunner.OnNodeFinished(activeNode); //SIGNAL COMPLETION, allowing the waiting Experiment Runner to proceed activeNode.SignalCompletion(); } //sw.Stop(); //System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.Name + ": " + sw.ElapsedMilliseconds); //System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.Name + ": " + sw.Elapsed.TotalMilliseconds); //System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.Name + ": " + (sw.ElapsedTicks)); }
public bool Equals(RunnableNodeThreadArgs otherArgs) { if (otherArgs == null) { throw new ArgumentNullException("otherArgs"); } bool areEqual = ExperimentRunner == otherArgs.ExperimentRunner; areEqual &= Node == otherArgs.Node; return(areEqual); }
/// <summary> /// Executes the experiment. /// </summary> /// <param name="progress">The progress.</param> public void ExecuteExperiment(IProgress progress) { try { bool successful = true; string endMessage = Messages.ExperimentRunnerSuccessMessage; OnExperimentStarted(); if (m_runnableExperiment.IsEmpty == false) { if (progress != null) { progress.Reset(); progress.NumSteps = m_runnableExperiment.Nodes.Count; // Start at 1 so user can tell something is happening. progress.Increment(); progress.CurrentStatus = Messages.ProgressExperimentProcessing; } // collection of nodes currently executing ActiveNodesList currentActiveNodesList = new ActiveNodesList(m_runnableExperiment.TerminateExperimentExecutionResetEvent); // collection of nodes pending to be started Queue <RunnableNode> pendingNodesToBeRun = new Queue <RunnableNode>(); // enqueue start node pendingNodesToBeRun.Enqueue(m_runnableExperiment.StartNode); bool end = false; while (!end) //until end component is not completed { //activate all pending nodes while (pendingNodesToBeRun.Count > 0) { RunnableNode node = pendingNodesToBeRun.Dequeue(); if (currentActiveNodesList.Contains(node) == false) { RunnableNodeThreadArgs args = new RunnableNodeThreadArgs { ExperimentRunner = this }; var resetEvent = node.Run(args); currentActiveNodesList.Add(node, resetEvent); } } if (currentActiveNodesList.Count > 0) { //wait for any node to be completed int index = WaitHandle.WaitAny(currentActiveNodesList.NodeResetEvents); //the index 0 is the termination signal... if the index is higher than zero then process the completed node if (index > 0) { RunnableNode completedNode = currentActiveNodesList.TakeOutNode(index); if (progress != null) { progress.Increment(); } // if experiment runner reaches end node, then prepare to exit the experiment runner if (completedNode.Equals(m_runnableExperiment.EndNode)) { end = true; // if there are any other nodes still running other than end node if (currentActiveNodesList.Count > 1) { successful = false; endMessage = Messages.ExperimentRunnerErrorMessage; TerminateExperimentExecution(); //send signal terminate in case sth else in sub level experiment is running NLog.LogManager.GetCurrentClassLogger().Error(Messages.ExperimentRunnerEarlyTerminationErrorMessage); } } else { // send one token to all successor nodes foreach (RunnableNode successorNode in completedNode.NextNodes) { //sends token; method will return true if successor node is ready to be run bool readyToRun = successorNode.SendToken(); if (readyToRun) { //add node to the pending nodes to be activated pendingNodesToBeRun.Enqueue(successorNode); } } } } else { //EXECUTED ON SIGNAL TERMINATED // If any node signal TERMINATE for any reason, we shut down the experiment and stop processing new nodes. end = true; successful = false; endMessage = Messages.ExperimentExecutionTerminated; System.Diagnostics.Trace.WriteLine("TERMINATED!"); } } else { end = true; successful = false; endMessage = Messages.ExperimentRunnerInfiniteWaitDetected; TerminateExperimentExecution(); //send signal terminate in case sth else in sub level experiment is running System.Diagnostics.Trace.WriteLine("Infinite wait detected!"); } } // while(!end) //wait if there are any still running threads, only in case if experiment runner ended on termination foreach (RunnableNode n in currentActiveNodesList.Nodes) { //Blocks this thread until all node threads terminate. n.JoinNodeThread(); } } else // if (m_runnableExperiment.IsEmpty == false) { #if DEBUG NLog.LogManager.GetCurrentClassLogger().Debug("RunnableExperiment is empty"); #endif successful = false; endMessage = Messages.ExperimentRunnerErrorMessage; } if (progress != null) { progress.Reset(); if (!successful) { progress.SetError(true); } progress.CurrentStatus = endMessage; } } finally { if (m_disposeRunnableExperiment == true) { // destroy components app domain... note the app domain should not be destroyed by sub level experiments TraceLab.Core.Components.LibraryHelper.DestroyDomain(m_runnableExperiment.ComponentsAppDomain); //dispose entire experiment - it disposes all subexperiments as well. m_runnableExperiment.Dispose(); } OnExperimentFinished(); } }
/// <summary> /// Executes the experiment. /// </summary> /// <param name="progress">The progress.</param> public void ExecuteExperiment(IProgress progress) { try { bool successful = true; string endMessage = Messages.ExperimentRunnerSuccessMessage; OnExperimentStarted(); if (m_runnableExperiment.IsEmpty == false) { if (progress != null) { progress.Reset(); progress.NumSteps = m_runnableExperiment.Nodes.Count; // Start at 1 so user can tell something is happening. progress.Increment(); progress.CurrentStatus = Messages.ProgressExperimentProcessing; } // collection of nodes currently executing ActiveNodesList currentActiveNodesList = new ActiveNodesList(m_runnableExperiment.TerminateExperimentExecutionResetEvent); // collection of nodes pending to be started Queue<RunnableNode> pendingNodesToBeRun = new Queue<RunnableNode>(); // enqueue start node pendingNodesToBeRun.Enqueue(m_runnableExperiment.StartNode); bool end = false; while (!end) //until end component is not completed { //activate all pending nodes while (pendingNodesToBeRun.Count > 0) { RunnableNode node = pendingNodesToBeRun.Dequeue(); if (currentActiveNodesList.Contains(node) == false) { RunnableNodeThreadArgs args = new RunnableNodeThreadArgs { ExperimentRunner = this }; var resetEvent = node.Run(args); currentActiveNodesList.Add(node, resetEvent); } } if (currentActiveNodesList.Count > 0) { //wait for any node to be completed int index = WaitHandle.WaitAny(currentActiveNodesList.NodeResetEvents); //the index 0 is the termination signal... if the index is higher than zero then process the completed node if (index > 0) { RunnableNode completedNode = currentActiveNodesList.TakeOutNode(index); if (progress != null) { progress.Increment(); } // if experiment runner reaches end node, then prepare to exit the experiment runner if (completedNode.Equals(m_runnableExperiment.EndNode)) { end = true; // if there are any other nodes still running other than end node if (currentActiveNodesList.Count > 1) { successful = false; endMessage = Messages.ExperimentRunnerErrorMessage; TerminateExperimentExecution(); //send signal terminate in case sth else in sub level experiment is running NLog.LogManager.GetCurrentClassLogger().Error(Messages.ExperimentRunnerEarlyTerminationErrorMessage); } } else { // send one token to all successor nodes foreach (RunnableNode successorNode in completedNode.NextNodes) { //sends token; method will return true if successor node is ready to be run bool readyToRun = successorNode.SendToken(); if (readyToRun) { //add node to the pending nodes to be activated pendingNodesToBeRun.Enqueue(successorNode); } } } } else { //EXECUTED ON SIGNAL TERMINATED // If any node signal TERMINATE for any reason, we shut down the experiment and stop processing new nodes. end = true; successful = false; endMessage = Messages.ExperimentExecutionTerminated; System.Diagnostics.Trace.WriteLine("TERMINATED!"); } } else { end = true; successful = false; endMessage = Messages.ExperimentRunnerInfiniteWaitDetected; TerminateExperimentExecution(); //send signal terminate in case sth else in sub level experiment is running System.Diagnostics.Trace.WriteLine("Infinite wait detected!"); } } // while(!end) //wait if there are any still running threads, only in case if experiment runner ended on termination foreach (RunnableNode n in currentActiveNodesList.Nodes) { //Blocks this thread until all node threads terminate. n.JoinNodeThread(); } } else // if (m_runnableExperiment.IsEmpty == false) { #if DEBUG NLog.LogManager.GetCurrentClassLogger().Debug("RunnableExperiment is empty"); #endif successful = false; endMessage = Messages.ExperimentRunnerErrorMessage; } if (progress != null) { progress.Reset(); if (!successful) { progress.SetError(true); } progress.CurrentStatus = endMessage; } } finally { if (m_disposeRunnableExperiment == true) { // destroy components app domain... note the app domain should not be destroyed by sub level experiments TraceLab.Core.Components.LibraryHelper.DestroyDomain(m_runnableExperiment.ComponentsAppDomain); //dispose entire experiment - it disposes all subexperiments as well. m_runnableExperiment.Dispose(); } OnExperimentFinished(); } }
/// <summary> /// Runs creates the thread with specified specified arguments and starts this thread. /// </summary> /// <param name="args">The args.</param> /// <returns>The the AutoResetEvent that will signal, when the thread finishes.</returns> public AutoResetEvent Run(RunnableNodeThreadArgs args) { if (args == null || args.ExperimentRunner == null) throw new ArgumentNullException("args", "RunnableNodeThreadArgs and its dispatcher cannot be null to start a thread"); args.Node = this; // Sets the state of the reset event to nonsignaled m_nodeResetEvent.Reset(); // Create a task and supply a user delegate by using a lambda expression. var nodeThread = ThreadFactory.CreateThread(new ParameterizedThreadStart(ThreadRun)); nodeThread.Name = String.Format("Worker: {0}, {1}", Id, Label); nodeThread.IsBackground = true; nodeThread.SetApartmentState(ApartmentState.STA); nodeThread.Start(args); m_nodeThread = nodeThread; return m_nodeResetEvent; }