Parallel Task should display its subtasks statuts when building (Feature #47)


Added by Olivier Sannier about 6 years ago. Updated about 6 years ago.


Status:Closed Start date:01/04/2012
Priority:Normal Due date:
Assignee:- % Done:

0%

Category:- Spent time: -
Target version:1.7

Description

From JIRA: http://jira.public.thoughtworks.org/browse/CCNET-1958

Following on issue #46 I made a few changes to the ParallelTask so that it too can show the statuses for its subtasks while they run.
The changes below need the changes made to BuildProgressInformation as described in the last comment by me on the above mentioned issue. They should replace the code that is at the end of the class, near the "protected" region.

private class _RunningSubTaskStatus
{
private IIntegrationResult _ParentResult;
public _RunningSubTaskStatus(IIntegrationResult ParentResult)
{
_ParentResult = ParentResult;
Finished = false;
}
public string Information { get; set; }
public bool Finished { get; set; }
public IIntegrationResult ParentResult { get { return _ParentResult; } }
}
private _RunningSubTaskStatus[] _TasksStatuses;
private string _getStatusInformation(bool ShowTasksStatus)
{
string Value = !string.IsNullOrEmpty(Description)
? Description
: string.Format("Running parallel tasks ({0} task(s))", Tasks.Length);
if (ShowTasksStatus)
{
Value = ": ";
for (var loop = 0; loop < Tasks.Length; loop
+) {
var Status = _TasksStatuses[loop];
if (!Status.Finished)
Value += string.Format("[{0}] {1} --- ",
loop,
!string.IsNullOrEmpty(Status.Information)
? Status.Information
: "No information");
}
}
return Value;
}
#region Protected methods
#region Execute()
/// &lt;summary&gt;
/// Runs the task, given the specified &lt;see cref="IIntegrationResult"/&gt;, in the specified &lt;see cref="IProject"/&gt;.
/// &lt;/summary&gt;
/// &lt;param name="result"&gt;&lt;/param&gt;
protected override bool Execute(IIntegrationResult result) {
// Initialise the task
var logger = Logger ?? new DefaultLogger();
var numberOfTasks = Tasks.Length;
_TasksStatuses = new _RunningSubTaskStatus[numberOfTasks];
result.BuildProgressInformation.SignalStartRunTask(_getStatusInformation(false));
logger.Info("Starting parallel task with {0} sub-task(s)", numberOfTasks);

// Initialise the arrays
var events = new ManualResetEvent[numberOfTasks];
var results = new IIntegrationResult[numberOfTasks];

// Launch each task using the ThreadPool
var countLock = new object();
var successCount = 0;
var failureCount = 0;
for (var loop = 0; loop < numberOfTasks; loop++) {
events[loop] = new ManualResetEvent(false);
results[loop] = result.Clone();
_TasksStatuses[loop] = new _RunningSubTaskStatus(/*results[loop], */result);
ThreadPool.QueueUserWorkItem((state) => {
var taskNumber = (int)state;
var taskName = string.Format("{0} [{1}]", Tasks[taskNumber].GetType().Name, taskNumber);
try {
Thread.CurrentThread.Name = string.Format("{0} [Parallel-{1}]", result.ProjectName, taskNumber);
logger.Debug("Starting task '{0}'", taskName);

// Start the actual task
var task = Tasks[taskNumber];
var taskResult = results[taskNumber];
taskResult.BuildProgressInformation.OnStartupInformationUpdatedUserObject = _TasksStatuses[taskNumber];
taskResult.BuildProgressInformation.OnStartupInformationUpdated = SubTaskStartupInformationUpdated;
RunTask(task, taskResult);
}
catch (Exception error) {
// Handle any error details
results[taskNumber].ExceptionResult = error;
results[taskNumber].Status = IntegrationStatus.Failure;
logger.Warning("Task '{0}' failed!", taskName);
}
// Record the results
lock (countLock) {
if (results[taskNumber].Status == IntegrationStatus.Success) {
successCount++;
}
else {
failureCount++;
}
}
// Tell everyone the task is done
events[taskNumber].Set();
_TasksStatuses[taskNumber].Finished = true;
_TasksStatuses[taskNumber].ParentResult.BuildProgressInformation.UpdateStartupInformation(_getStatusInformation(true));
}, loop);

}

// Wait for all the tasks to complete
logger.Debug("Waiting for tasks to complete");
WaitHandle.WaitAll(events);

// Merge all the results
logger.Info("Merging task results");
foreach (var taskResult in results) {
result.Merge(taskResult);
}

// Clean up
this.CancelTasks();
logger.Info("Parallel task completed: {0} successful, {1} failed", successCount, failureCount);
return true;
}
#endregion
#endregion

private void SubTaskStartupInformationUpdated(string information, object UserObject)
{
var Status = ((_RunningSubTaskStatus)UserObject);
Status.Information = information;
Status.ParentResult.BuildProgressInformation.UpdateStartupInformation(_getStatusInformation(true));
}
}

The project to test this is the following:

  <project name="ParallelTest">
    <tasks>
      <parallel>
        <tasks>
          <exec>
            <description>Parallel Level 1 - Exec task 1</description>
            <buildArgs>/c ping -n 10 127.0.0.1</buildArgs>
            <executable>cmd.exe</executable>
            <successExitCodes>0</successExitCodes>
          </exec>
          <exec>
            <description>Parallel Level 1 - Exec task 2</description>
            <buildArgs>/c ping -n 15 127.0.0.1</buildArgs>
            <executable>cmd.exe</executable>
            <successExitCodes>0</successExitCodes>
          </exec>
          <parallel>
            <tasks>
              <exec>
                <description>Parallel Level 2 - Exec task 1</description>
                <buildArgs>/c ping -n 25 127.0.0.1</buildArgs>
                <executable>cmd.exe</executable>
                <successExitCodes>0</successExitCodes>
              </exec>
              <exec>
                <description>Parallel Level 2 - Exec task 2</description>
                <buildArgs>/c ping -n 20 127.0.0.1</buildArgs>
                <executable>cmd.exe</executable>
                <successExitCodes>0</successExitCodes>
              </exec>
            </tasks>
          </parallel>
        </tasks>
      </parallel>
    </tasks>
  </project>

Hope this helps


History

Updated by Daniel Hommel about 6 years ago

Pull request merged.

  • Status changed from New to Resolved

Updated by Ruben Willems about 6 years ago

  • Target version set to 1.7
  • Status changed from Resolved to Closed

Also available in: Atom PDF