public static async Task PrintNodeTasksAsync(BatchClient batchClient, string poolId) { Console.WriteLine("Listing Node Tasks"); Console.WriteLine("=================="); ODATADetailLevel nodeDetail = new ODATADetailLevel(selectClause: "id,recentTasks"); IPagedEnumerable <ComputeNode> nodes = batchClient.PoolOperations.ListComputeNodes(poolId, nodeDetail); await nodes.ForEachAsync(node => { Console.WriteLine(); Console.WriteLine(node.Id + " tasks:"); if (node.RecentTasks != null && node.RecentTasks.Any()) { foreach (TaskInformation task in node.RecentTasks) { Console.WriteLine("\t{0}: {1}", task.TaskId, task.TaskState); } } else { // No tasks found for the node Console.WriteLine("\tNone"); } }).ConfigureAwait(continueOnCapturedContext: false); Console.WriteLine("=================="); }
public async Task IfSequenceIsNull_ThenForEachAsyncThrowsArgumentNullException_SyncDelegateOverload() { IPagedEnumerable <string> seq = null; var ex = await Assert.ThrowsAsync <ArgumentNullException>(() => seq.ForEachAsync(_ => { })); Assert.Equal("source", ex.ParamName); }
private async System.Threading.Tasks.Task <List <TaskModel> > ListTasksAsync() { List <TaskModel> results = new List <TaskModel>(); IPagedEnumerable <CloudTask> taskList = this.Job.ListTasks(OptionsModel.Instance.ListDetailLevel); await taskList.ForEachAsync(item => results.Add(new TaskModel(this, item))); return(results); }
private async Task <List <ComputeNodeModel> > ListComputeNodesAsync() { List <ComputeNodeModel> results = new List <ComputeNodeModel>(); IPagedEnumerable <ComputeNode> jobList = this.Pool.ListComputeNodes(); await jobList.ForEachAsync(item => results.Add(new ComputeNodeModel(this, item))); return(results); }
public async Task <IList <JobModel> > GetJobCollectionAsync() { IPagedEnumerable <CloudJob> jobs = this.Service.ListJobs(OptionsModel.Instance.ListDetailLevel); List <JobModel> jobModels = new List <JobModel>(); await jobs.ForEachAsync(item => jobModels.Add(new JobModel(item))); return(jobModels); }
public async Task <IList <PoolModel> > GetPoolCollectionAsync() { IPagedEnumerable <CloudPool> pools = this.Service.ListPools(OptionsModel.Instance.ListDetailLevel); IList <PoolModel> poolModels = new List <PoolModel>(); await pools.ForEachAsync(item => poolModels.Add(new PoolModel(item))); return(poolModels); }
public async Task <IList <CertificateModel> > GetCertificatesCollectionAsync() { IPagedEnumerable <Certificate> certificates = this.Service.ListCertificates(null); IList <CertificateModel> certificateModels = new List <CertificateModel>(); await certificates.ForEachAsync(item => certificateModels.Add(new CertificateModel(item))); return(certificateModels); }
/// <summary> /// Iterates over an <see cref="IPagedEnumerable{T}"/> sequence, invoking an asynchronous delegate for each element. /// </summary> /// <param name="source">The <see cref="IPagedEnumerable{T}"/> to iterate over.</param> /// <param name="body">The asynchronous delegate to execute for each element in <paramref name="source"/>.</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> for controlling the lifetime of the asynchronous operation.</param> /// <returns>A <see cref="System.Threading.Tasks.Task"/> that represents the iteration operation. The task /// completes when iteration is complete.</returns> /// <remarks>This method processes elements sequentially, not concurrently. That is, for each element in the /// sequence, the method awaits the asynchronous delegate before processing the next element.</remarks> public static async Task ForEachAsync <T>(this IPagedEnumerable <T> source, Func <T, Task> body, CancellationToken cancellationToken = default(CancellationToken)) { if (source == null) { throw new ArgumentNullException("source"); } if (body == null) { throw new ArgumentNullException("body"); } await source.ForEachAsync((t, ct) => body(t), cancellationToken).ConfigureAwait(false); }
/// <summary> /// Creates a <see cref="List{T}" /> from an <see cref="IPagedEnumerable{T}"/>. /// </summary> /// <param name="source">The <see cref="IPagedEnumerable{T}"/> to create a list from.</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> for controlling the lifetime of the asynchronous operation.</param> /// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous operation. The result /// of the task is a <see cref="List{T}" /> containing all elements of the source sequence.</returns> public static async Task <List <T> > ToListAsync <T>(this IPagedEnumerable <T> source, CancellationToken cancellationToken = default(CancellationToken)) { if (source == null) { throw new ArgumentNullException("source"); } List <T> results = new List <T>(); await source.ForEachAsync(item => results.Add(item), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return(results); }
private async Task <List <JobModel> > ListJobsAsync() { List <JobModel> results = new List <JobModel>(); var detailLevel = new ODATADetailLevel() { SelectClause = "id,state,creationTime" }; IPagedEnumerable <CloudJob> jobList = this.JobSchedule.ListJobs(detailLevel); await jobList.ForEachAsync(item => results.Add(new JobModel(item))); return(results); }
/// <summary> /// Lists all the jobs in the Batch account. /// </summary> /// <param name="batchClient">The BatchClient to use when interacting with the Batch service.</param> /// <returns>An asynchronous <see cref="Task"/> representing the operation.</returns> public static async Task PrintJobsAsync(BatchClient batchClient) { Console.WriteLine("Listing Jobs"); Console.WriteLine("============"); IPagedEnumerable <CloudJob> jobs = batchClient.JobOperations.ListJobs(new ODATADetailLevel(selectClause: "id,state")); await jobs.ForEachAsync(job => { Console.WriteLine("State of job " + job.Id + " is " + job.State); }).ConfigureAwait(continueOnCapturedContext: false); Console.WriteLine("============"); }
/// <summary> /// Lists all the jobs in the Batch account. /// </summary> /// <param name="batchClient">The BatchClient to use when interacting with the Batch service.</param> /// <returns>An asynchronous <see cref="Task"/> representing the operation.</returns> private static async Task ListJobsAsync(BatchClient batchClient) { Console.WriteLine("Listing Jobs"); Console.WriteLine("============"); IPagedEnumerable <CloudJob> jobs = batchClient.JobOperations.ListJobs(new ODATADetailLevel(selectClause: "id,state")); await jobs.ForEachAsync(job => { Console.WriteLine("State of job " + job.Id + " is " + job.State); }); Console.WriteLine("============"); }
/// <summary> /// Lists all the pools in the Batch account. /// </summary> /// <param name="batchClient">The BatchClient to use when interacting with the Batch service.</param> /// <returns>An asynchronous <see cref="Task"/> representing the operation.</returns> public static async Task PrintPoolsAsync(BatchClient batchClient) { Console.WriteLine("Listing Pools"); Console.WriteLine("============="); // Using optional select clause to return only the properties of interest. Makes query faster and reduces HTTP packet size impact IPagedEnumerable <CloudPool> pools = batchClient.PoolOperations.ListPools(new ODATADetailLevel(selectClause: "id,state,currentDedicated,vmSize")); await pools.ForEachAsync(pool => { Console.WriteLine("State of pool {0} is {1} and it has {2} nodes of size {3}", pool.Id, pool.State, pool.CurrentDedicated, pool.VirtualMachineSize); }).ConfigureAwait(continueOnCapturedContext: false); Console.WriteLine("============="); }
/// <summary> /// Prints running task and task slot counts to the console for each of the nodes in the specified pool. /// </summary> /// <param name="batchClient">The Batch client.</param> /// <param name="poolId">The ID of the <see cref="CloudPool"/> containing the nodes whose task information should be printed to the console.</param> /// <returns>A <see cref="System.Threading.Tasks.Task"/> object that represents the asynchronous operation.</returns> public static async Task PrintNodeTaskCountsAsync(BatchClient batchClient, string poolId) { Console.WriteLine("Listing Node Running Task Counts"); Console.WriteLine("=================="); ODATADetailLevel nodeDetail = new ODATADetailLevel(selectClause: "id,runningTasksCount,runningTaskSlotsCount"); IPagedEnumerable <ComputeNode> nodes = batchClient.PoolOperations.ListComputeNodes(poolId, nodeDetail); await nodes.ForEachAsync(node => { Console.WriteLine(); Console.WriteLine(node.Id + " :"); Console.WriteLine($"RunningTasks = {node.RunningTasksCount}, RunningTaskSlots = {node.RunningTaskSlotsCount}"); }).ConfigureAwait(continueOnCapturedContext: false); Console.WriteLine("=================="); }
private async Task WaitForMapperTasksToCompleteAsync(BatchClient batchClient) { Console.WriteLine("Waiting for the mapper tasks to complete..."); //List all the mapper tasks using an id filter. DetailLevel mapperTaskIdFilter = new ODATADetailLevel() { FilterClause = string.Format("startswith(id, '{0}')", Constants.MapperTaskPrefix) }; IEnumerable <CloudTask> tasksToMonitor = batchClient.JobOperations.ListTasks( this.jobId, detailLevel: mapperTaskIdFilter); // Use the task state monitor to wait for the tasks to complete. Monitoring the tasks // for completion is necessary if you are using KillJobOnCompletion = TRUE, as otherwise when the job manager // exits it will kill all of the tasks that are still running under the job. TaskStateMonitor taskStateMonitor = batchClient.Utilities.CreateTaskStateMonitor(); bool timedOut = await taskStateMonitor.WaitAllAsync(tasksToMonitor, TaskState.Completed, TimeSpan.FromMinutes(5)); //Get the list of mapper tasks in order to analyze their state and ensure they completed successfully. IPagedEnumerable <CloudTask> asyncEnumerable = batchClient.JobOperations.ListTasks( this.jobId, detailLevel: mapperTaskIdFilter); await asyncEnumerable.ForEachAsync(async cloudTask => { Console.WriteLine("Task {0} is in state: {1}", cloudTask.Id, cloudTask.State); await Helpers.CheckForTaskSuccessAsync(cloudTask, dumpStandardOutOnTaskSuccess: false); Console.WriteLine(); }); //If not all the tasks reached the desired state within the timeout then the job manager //cannot continue. if (timedOut) { const string errorMessage = "Mapper tasks did not complete within expected timeout."; Console.WriteLine(errorMessage); throw new TimeoutException(errorMessage); } }
public async Task<IList<JobModel>> GetJobCollectionAsync(string jobSearchFilter) { IPagedEnumerable<CloudJob> jobs = this.Service.ListJobs(OptionsModel.Instance.ListDetailLevel); List<JobModel> jobModels = new List<JobModel>(); // The properties we want to filter on are not available in a ODATADetailLevel query. Filter them client side if (!String.IsNullOrWhiteSpace(jobSearchFilter)) { var jobSearchFilterL = jobSearchFilter.ToLowerInvariant(); var filteredJobs = jobs.Where(f => f.DisplayName.ToLowerInvariant().Contains(jobSearchFilterL) || f.Id.ToLowerInvariant().Contains(jobSearchFilterL) || f.Metadata.Any(g => g.Name.ToLowerInvariant().Contains(jobSearchFilterL)) || f.Metadata.Any(g => g.Value.ToLowerInvariant().Contains(jobSearchFilterL))); jobModels.AddRange(filteredJobs.Select(item => new JobModel(item))); } else { await jobs.ForEachAsync(item => jobModels.Add(new JobModel(item))); } return jobModels; }
private async Task <List <JobModel> > ListJobsAsync(int min, int max) { List <JobModel> results = new List <JobModel>(); string uppperBound = string.Format("job-{0:D10}", max); string lowerBound = string.Format("job-{0:D10}", min); // TODO: Need to use the detail level to limit amount of data we download from the server // TODO: and increase the performace of listing jobs in the UI //var detailLevel = new ODATADetailLevel() { SelectClause = "id,state,creationTime" }; //if (string.IsNullOrEmpty(detailLevel.FilterClause)) //{ // detailLevel.FilterClause = string.Empty; //} //detailLevel.FilterClause += string.Format("(jobId le '{0}' and jobId gt '{1}')", uppperBound, lowerBound); //IEnumerableAsyncExtended<CloudJob> jobList = this.JobSchedule.ListJobs(detailLevel); // END TODO IPagedEnumerable <CloudJob> jobList = this.JobSchedule.ListJobs(); await jobList.ForEachAsync(item => results.Add(new JobModel(item))); return(results); }
/// <summary> /// Runs the job manager task. /// </summary> public async Task RunAsync() { Console.WriteLine("JobManager for account: {0}, job: {1} has started...", this.accountName, this.jobId); Console.WriteLine(); Console.WriteLine("JobManager running with the following settings: "); Console.WriteLine("----------------------------------------"); Console.WriteLine(this.configurationSettings.ToString()); //Set up the Batch Service credentials used to authenticate with the Batch Service. BatchSharedKeyCredentials batchSharedKeyCredentials = new BatchSharedKeyCredentials( this.configurationSettings.BatchServiceUrl, this.configurationSettings.BatchAccountName, this.configurationSettings.BatchAccountKey); using (BatchClient batchClient = await BatchClient.OpenAsync(batchSharedKeyCredentials)) { //Construct a container SAS to provide the Batch Service access to the files required to //run the mapper and reducer tasks. string containerSas = Helpers.ConstructContainerSas( this.configurationSettings.StorageAccountName, this.configurationSettings.StorageAccountKey, this.configurationSettings.StorageServiceUrl, this.configurationSettings.BlobContainer); // // Submit mapper tasks. // Console.WriteLine("Submitting {0} mapper tasks.", this.configurationSettings.NumberOfMapperTasks); //The collection of tasks to add to the Batch Service. List <CloudTask> tasksToAdd = new List <CloudTask>(); for (int i = 0; i < this.configurationSettings.NumberOfMapperTasks; i++) { string taskId = Helpers.GetMapperTaskId(i); string fileBlobName = Helpers.GetSplitFileName(i); string fileBlobPath = Helpers.ConstructBlobSource(containerSas, fileBlobName); string commandLine = string.Format("{0} -MapperTask {1}", Constants.TextSearchExe, fileBlobPath); CloudTask unboundMapperTask = new CloudTask(taskId, commandLine); //The set of files (exes, dlls and configuration files) required to run the mapper task. IReadOnlyList <string> mapperTaskRequiredFiles = Constants.RequiredExecutableFiles; List <ResourceFile> mapperTaskResourceFiles = Helpers.GetResourceFiles(containerSas, mapperTaskRequiredFiles); unboundMapperTask.ResourceFiles = mapperTaskResourceFiles; tasksToAdd.Add(unboundMapperTask); } //Submit the unbound task collection to the Batch Service. //Use the AddTask method which takes a collection of CloudTasks for the best performance. await batchClient.JobOperations.AddTaskAsync(this.jobId, tasksToAdd); // // Wait for the mapper tasks to complete. // Console.WriteLine("Waiting for the mapper tasks to complete..."); //List all the mapper tasks using an id filter. DetailLevel mapperTaskIdFilter = new ODATADetailLevel() { FilterClause = string.Format("startswith(id, '{0}')", Constants.MapperTaskPrefix) }; IEnumerable <CloudTask> tasksToMonitor = batchClient.JobOperations.ListTasks( this.jobId, detailLevel: mapperTaskIdFilter); //Use the task state monitor to wait for the tasks to complete. TaskStateMonitor taskStateMonitor = batchClient.Utilities.CreateTaskStateMonitor(); bool timedOut = await taskStateMonitor.WaitAllAsync(tasksToMonitor, TaskState.Completed, TimeSpan.FromMinutes(5)); //Get the list of mapper tasks in order to analyze their state and ensure they completed successfully. IPagedEnumerable <CloudTask> asyncEnumerable = batchClient.JobOperations.ListTasks( this.jobId, detailLevel: mapperTaskIdFilter); await asyncEnumerable.ForEachAsync(async cloudTask => { Console.WriteLine("Task {0} is in state: {1}", cloudTask.Id, cloudTask.State); await Helpers.CheckForTaskSuccessAsync(cloudTask, dumpStandardOutOnTaskSuccess: false); Console.WriteLine(); }); //If not all the tasks reached the desired state within the timeout then the job manager //cannot continue. if (timedOut) { const string errorMessage = "Mapper tasks did not complete within expected timeout."; Console.WriteLine(errorMessage); throw new TimeoutException(errorMessage); } // // Create the reducer task. // string reducerTaskCommandLine = string.Format("{0} -ReducerTask", Constants.TextSearchExe); Console.WriteLine("Adding the reducer task: {0}", Constants.ReducerTaskId); CloudTask unboundReducerTask = new CloudTask(Constants.ReducerTaskId, reducerTaskCommandLine); //The set of files (exes, dlls and configuration files) required to run the reducer task. List <ResourceFile> reducerTaskResourceFiles = Helpers.GetResourceFiles(containerSas, Constants.RequiredExecutableFiles); unboundReducerTask.ResourceFiles = reducerTaskResourceFiles; //Send the request to the Batch Service to add the reducer task. await batchClient.JobOperations.AddTaskAsync(this.jobId, unboundReducerTask); // //Wait for the reducer task to complete. // //Get the bound reducer task and monitor it for completion. CloudTask boundReducerTask = await batchClient.JobOperations.GetTaskAsync(this.jobId, Constants.ReducerTaskId); timedOut = await taskStateMonitor.WaitAllAsync(new List <CloudTask> { boundReducerTask }, TaskState.Completed, TimeSpan.FromMinutes(2)); //Refresh the reducer task to get the most recent information about it from the Batch Service. await boundReducerTask.RefreshAsync(); //Dump the reducer tasks exit code and scheduling error for debugging purposes. await Helpers.CheckForTaskSuccessAsync(boundReducerTask, dumpStandardOutOnTaskSuccess : true); //Handle the possibilty that the reducer task did not complete in the expected timeout. if (timedOut) { const string errorMessage = "Reducer task did not complete within expected timeout."; Console.WriteLine("Task {0} is in state: {1}", boundReducerTask.Id, boundReducerTask.State); Console.WriteLine(errorMessage); throw new TimeoutException(errorMessage); } //The job manager has completed. Console.WriteLine("JobManager completed successfully."); } }
public static async Task MainAsync() { const string poolId = "MultiInstanceSamplePool"; const string jobId = "MultiInstanceSampleJob"; const string taskId = "MultiInstanceSampleTask"; const int numberOfNodes = 5; //jmeno package kterou uploaduju na azure s polu s MSMpiSetup const string appPackageId = "Parallel"; const string appPackageVersion = "1.0"; TimeSpan timeout = TimeSpan.FromMinutes(15); AccountSettings accountSettings = SampleHelpers.LoadAccountSettings(); //nakonfigurované batch accounty abych se mohl připojit ke svému účtu BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials( accountSettings.BatchServiceUrl, accountSettings.BatchAccountName, accountSettings.BatchAccountKey); using (BatchClient batchClient = BatchClient.Open(cred)) { // Vytvoření fondu výpočetních uzlů a úlohu, do které přidáme úlohu s více instancemi. await CreatePoolAsync(batchClient, poolId, numberOfNodes, appPackageId, appPackageVersion); await CreateJobAsync(batchClient, jobId, poolId); //batch vytvoří jednu hlavní a několik dílčích úkolů CloudTask multiInstanceTask = new CloudTask(id: taskId, commandline: $"cmd /c mpiexec.exe -c 1 -wdir %AZ_BATCH_TASK_SHARED_DIR% %AZ_BATCH_APP_PACKAGE_{appPackageId.ToUpper()}#{appPackageVersion}%\\ParallelMpiApp.exe"); // příkaz SPMD = více samostatných procesorů současně spouští stejný program multiInstanceTask.MultiInstanceSettings = new MultiInstanceSettings(@"cmd /c start cmd /c smpd.exe -d", numberOfNodes); //zadání úkolů, vytvoří se jeden primární a několik dílčích, //aby odpovídaly počtu uzlů a naplánuje se jejich provedení v uzlech Console.WriteLine($"Adding task [{taskId}] to job [{jobId}]..."); await batchClient.JobOperations.AddTaskAsync(jobId, multiInstanceTask); //verze úlohy CloudTask mainTask = await batchClient.JobOperations.GetTaskAsync(jobId, taskId); // sledování stavu úkolů,čekáme až bude úloha dokončena Console.WriteLine($"Awaiting task completion, timeout in {timeout}..."); TaskStateMonitor taskStateMonitor = batchClient.Utilities.CreateTaskStateMonitor(); await taskStateMonitor.WhenAll(new List <CloudTask> { mainTask }, TaskState.Completed, timeout); //aktualizace úlohy await mainTask.RefreshAsync(); string stdOut = mainTask.GetNodeFile(Constants.StandardOutFileName).ReadAsString(); string stdErr = mainTask.GetNodeFile(Constants.StandardErrorFileName).ReadAsString(); Console.WriteLine(); Console.WriteLine($"Main task [{mainTask.Id}] is in state [{mainTask.State}] and ran on compute node [{mainTask.ComputeNodeInformation.ComputeNodeId}]:"); Console.WriteLine("---- stdout.txt ----"); Console.WriteLine(stdOut); Console.WriteLine("---- stderr.txt ----"); Console.WriteLine(stdErr); // par sekund čas aby se stačily dílčí úlohy dokončit TimeSpan subtaskTimeout = TimeSpan.FromSeconds(10); Console.WriteLine($"Main task completed, waiting {subtaskTimeout} for subtasks to complete..."); System.Threading.Thread.Sleep(subtaskTimeout); Console.WriteLine(); Console.WriteLine("---- Subtask information ----"); //kolekce dílčích úlohů a tisk informací o každém IPagedEnumerable <SubtaskInformation> subtasks = mainTask.ListSubtasks(); await subtasks.ForEachAsync(async (subtask) => { Console.WriteLine("subtask: " + subtask.Id); Console.WriteLine("\texit code: " + subtask.ExitCode); if (subtask.State == SubtaskState.Completed) { //získání souborů z uzlů ComputeNode node = await batchClient.PoolOperations.GetComputeNodeAsync(subtask.ComputeNodeInformation.PoolId, subtask.ComputeNodeInformation.ComputeNodeId); string outPath = subtask.ComputeNodeInformation.TaskRootDirectory + "\\" + Constants.StandardOutFileName; string errPath = subtask.ComputeNodeInformation.TaskRootDirectory + "\\" + Constants.StandardErrorFileName; NodeFile stdOutFile = await node.GetNodeFileAsync(outPath.Trim('\\')); NodeFile stdErrFile = await node.GetNodeFileAsync(errPath.Trim('\\')); stdOut = await stdOutFile.ReadAsStringAsync(); stdErr = await stdErrFile.ReadAsStringAsync(); Console.WriteLine($"\tnode: " + node.Id); Console.WriteLine("\tstdout.txt: " + stdOut); Console.WriteLine("\tstderr.txt: " + stdErr); } else { Console.WriteLine($"\tSubtask {subtask.Id} is in state {subtask.State}"); } }); // vymazání zdrojů které jsme vytvořili, abychom to nemuseli dělat manuálně(fondy,úlohy) Console.WriteLine(); Console.Write("Delete job? [yes] no: "); string response = Console.ReadLine().ToLower(); if (response != "n" && response != "no") { await batchClient.JobOperations.DeleteJobAsync(jobId); } Console.Write("Delete pool? [yes] no: "); response = Console.ReadLine().ToLower(); if (response != "n" && response != "no") { await batchClient.PoolOperations.DeletePoolAsync(poolId); } } }
public override async System.Threading.Tasks.Task RefreshAsync(ModelRefreshType refreshType, bool showTrackedOperation = true) { this.attemptToLoadOutputs = true; if (refreshType.HasFlag(ModelRefreshType.Basic)) { try { //await this.Task.RefreshAsync(); TODO: This doesnt' work right now due to bug with OM, so must do GetTask directly Messenger.Default.Send(new UpdateWaitSpinnerMessage(WaitSpinnerPanel.UpperRight, true)); System.Threading.Tasks.Task <CloudTask> asyncTask = MainViewModel.dataProvider.Service.GetTaskAsync( this.ParentJob.Id, this.Task.Id, OptionsModel.Instance.ListDetailLevel); if (showTrackedOperation) { AsyncOperationTracker.Instance.AddTrackedOperation(new AsyncOperationModel( asyncTask, new TaskOperation(TaskOperation.Refresh, this.ParentJob.Id, this.Task.Id))); } else { AsyncOperationTracker.Instance.AddTrackedInternalOperation(asyncTask); } this.Task = await asyncTask; this.LastUpdatedTime = DateTime.UtcNow; IPagedEnumerable <SubtaskInformation> subtasks = this.Task.ListSubtasks(OptionsModel.Instance.ListDetailLevel); this.SubtasksInfo = new List <SubtaskModel>(); await subtasks.ForEachAsync(item => this.SubtasksInfo.Add(new SubtaskModel(item))); // // Fire property change events for this models properties // this.FireChangesOnRefresh(ModelRefreshType.Basic); } catch (Exception e) { this.HandleException(e); } finally { Messenger.Default.Send(new UpdateWaitSpinnerMessage(WaitSpinnerPanel.UpperRight, false)); } } if (refreshType.HasFlag(ModelRefreshType.Children)) { try { Messenger.Default.Send(new UpdateWaitSpinnerMessage(WaitSpinnerPanel.LowerRight, true)); //Set this before the children load so that on revisit we know we have loaded the children (or are in the process) this.HasLoadedChildren = true; try { System.Threading.Tasks.Task <List <NodeFile> > asyncTask = this.ListTaskFilesAsync(); AsyncOperationTracker.Instance.AddTrackedOperation(new AsyncOperationModel( asyncTask, new TaskOperation(TaskOperation.ListFiles, this.ParentJob.Id, this.Task.Id))); this.OutputFiles = await asyncTask; } catch (BatchException be) { StringBuilder noOutputReasonBuilder = new StringBuilder(); if (be.RequestInformation != null && be.RequestInformation.AzureError != null) { if (!string.IsNullOrEmpty(be.RequestInformation.AzureError.Code)) { noOutputReasonBuilder.AppendLine(be.RequestInformation.AzureError.Code); } if (be.RequestInformation.AzureError.Message != null && !string.IsNullOrEmpty(be.RequestInformation.AzureError.Message.Value)) { noOutputReasonBuilder.AppendLine(be.RequestInformation.AzureError.Message.Value); } if (be.RequestInformation.AzureError.Values != null) { noOutputReasonBuilder.AppendLine(); foreach (var errorDetail in be.RequestInformation.AzureError.Values) { noOutputReasonBuilder.AppendLine(string.Format("{0}: {1}", errorDetail.Key, errorDetail.Value)); } } this.NoOutputFilesReason = noOutputReasonBuilder.ToString(); } } catch (Exception) { this.HasLoadedChildren = false; //On exception, we failed to load children so try again next time //Swallow the exception to stop popups from occuring for every bad VM } this.FireChangesOnRefresh(ModelRefreshType.Children); } catch (Exception e) { this.HasLoadedChildren = false; //On exception, we failed to load children so try again next time this.HandleException(e); } finally { Messenger.Default.Send(new UpdateWaitSpinnerMessage(WaitSpinnerPanel.LowerRight, false)); } } }
public static async Task MainAsync() { const string poolId = "MultiInstanceSamplePool"; const string jobId = "MultiInstanceSampleJob"; const string taskId = "MultiInstanceSampleTask"; const int numberOfNodes = 3; // The application package and version to deploy to the compute nodes. // It should contain your MPIHelloWorld sample MS-MPI program: // https://blogs.technet.microsoft.com/windowshpc/2015/02/02/how-to-compile-and-run-a-simple-ms-mpi-program/ // And the MSMpiSetup.exe installer: // https://www.microsoft.com/download/details.aspx?id=52981 // Then upload it as an application package: // https://azure.microsoft.com/documentation/articles/batch-application-packages/ const string appPackageId = "MPIHelloWorld"; const string appPackageVersion = "1.0"; TimeSpan timeout = TimeSpan.FromMinutes(30); // Configure your AccountSettings in the Microsoft.Azure.Batch.Samples.Common project within this solution BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(AccountSettings.Default.BatchServiceUrl, AccountSettings.Default.BatchAccountName, AccountSettings.Default.BatchAccountKey); using (BatchClient batchClient = BatchClient.Open(cred)) { // Create the pool of compute nodes and the job to which we add the multi-instance task. await CreatePoolAsync(batchClient, poolId, numberOfNodes, appPackageId, appPackageVersion); await CreateJobAsync(batchClient, jobId, poolId); // Create the multi-instance task. The MultiInstanceSettings property (configured // below) tells Batch to create one primary and several subtasks, the total number // of which matches the number of instances you specify in the MultiInstanceSettings. // This main task's command line is the "application command," and is executed *only* // by the primary, and only after the primary and all subtasks have executed the // "coordination command" (the MultiInstanceSettings.CoordinationCommandLine). CloudTask multiInstanceTask = new CloudTask(id: taskId, commandline: $"cmd /c mpiexec.exe -c 1 -wdir %AZ_BATCH_TASK_SHARED_DIR% %AZ_BATCH_APP_PACKAGE_{appPackageId.ToUpper()}#{appPackageVersion}%\\MPIHelloWorld.exe"); // Configure the task's MultiInstanceSettings. Specify the number of nodes // to allocate to the multi-instance task, and the "coordination command". // The CoordinationCommandLine is run by the primary and subtasks, and is // used in this sample to start SMPD on the compute nodes. multiInstanceTask.MultiInstanceSettings = new MultiInstanceSettings(@"cmd /c start cmd /c smpd.exe -d", numberOfNodes); // Submit the task to the job. Batch will take care of creating one primary and // enough subtasks to match the total number of nodes allocated to the task, // and schedule them for execution on the nodes. Console.WriteLine($"Adding task [{taskId}] to job [{jobId}]..."); await batchClient.JobOperations.AddTaskAsync(jobId, multiInstanceTask); // Get the "bound" version of the multi-instance task. CloudTask mainTask = await batchClient.JobOperations.GetTaskAsync(jobId, taskId); // We use a TaskStateMonitor to monitor the state of our tasks. In this case, // we will wait for the task to reach the Completed state. Console.WriteLine($"Awaiting task completion, timeout in {timeout}..."); TaskStateMonitor taskStateMonitor = batchClient.Utilities.CreateTaskStateMonitor(); await taskStateMonitor.WhenAll(new List <CloudTask> { mainTask }, TaskState.Completed, timeout); // Refresh the task to obtain up-to-date property values from Batch, such as // its current state and information about the node on which it executed. await mainTask.RefreshAsync(); string stdOut = mainTask.GetNodeFile(Constants.StandardOutFileName).ReadAsString(); string stdErr = mainTask.GetNodeFile(Constants.StandardErrorFileName).ReadAsString(); Console.WriteLine(); Console.WriteLine($"Main task [{mainTask.Id}] is in state [{mainTask.State}] and ran on compute node [{mainTask.ComputeNodeInformation.ComputeNodeId}]:"); Console.WriteLine("---- stdout.txt ----"); Console.WriteLine(stdOut); Console.WriteLine("---- stderr.txt ----"); Console.WriteLine(stdErr); // Need to delay a bit to allow the Batch service to mark the subtasks as Complete TimeSpan subtaskTimeout = TimeSpan.FromSeconds(10); Console.WriteLine($"Main task completed, waiting {subtaskTimeout} for subtasks to complete..."); System.Threading.Thread.Sleep(subtaskTimeout); Console.WriteLine(); Console.WriteLine("---- Subtask information ----"); // Obtain the collection of subtasks for the multi-instance task, and print // some information about each. IPagedEnumerable <SubtaskInformation> subtasks = mainTask.ListSubtasks(); await subtasks.ForEachAsync(async (subtask) => { Console.WriteLine("subtask: " + subtask.Id); Console.WriteLine("\texit code: " + subtask.ExitCode); if (subtask.State == SubtaskState.Completed) { // Obtain the file from the node on which the subtask executed. For normal CloudTasks, // we could simply call CloudTask.GetNodeFile(Constants.StandardOutFileName), but the // subtasks are not "normal" tasks in Batch, and thus must be handled differently. ComputeNode node = await batchClient.PoolOperations.GetComputeNodeAsync(subtask.ComputeNodeInformation.PoolId, subtask.ComputeNodeInformation.ComputeNodeId); string outPath = subtask.ComputeNodeInformation.TaskRootDirectory + "\\" + Constants.StandardOutFileName; string errPath = subtask.ComputeNodeInformation.TaskRootDirectory + "\\" + Constants.StandardErrorFileName; NodeFile stdOutFile = await node.GetNodeFileAsync(outPath.Trim('\\')); NodeFile stdErrFile = await node.GetNodeFileAsync(errPath.Trim('\\')); stdOut = await stdOutFile.ReadAsStringAsync(); stdErr = await stdErrFile.ReadAsStringAsync(); Console.WriteLine($"\tnode: " + node.Id); Console.WriteLine("\tstdout.txt: " + stdOut); Console.WriteLine("\tstderr.txt: " + stdErr); } else { Console.WriteLine($"\tSubtask {subtask.Id} is in state {subtask.State}"); } }); // Clean up the resources we've created in the Batch account Console.WriteLine(); Console.Write("Delete job? [yes] no: "); string response = Console.ReadLine().ToLower(); if (response != "n" && response != "no") { await batchClient.JobOperations.DeleteJobAsync(jobId); } Console.Write("Delete pool? [yes] no: "); response = Console.ReadLine().ToLower(); if (response != "n" && response != "no") { await batchClient.PoolOperations.DeletePoolAsync(poolId); } } }
private static async Task MainAsync(string[] args) { const string poolId = "JobPrepReleaseSamplePool"; const string jobId = "JobPrepReleaseSampleJob"; // Location of the file that the job tasks will work with, a text file in the // node's "shared" directory. const string taskOutputFile = "%AZ_BATCH_NODE_SHARED_DIR%\\job_prep_and_release.txt"; // The job prep task will write the node ID to the text file in the shared directory const string jobPrepCmdLine = "cmd /c echo %AZ_BATCH_NODE_ID% tasks: >" + taskOutputFile; // Each task then echoes its ID to the same text file const string taskCmdLine = "cmd /c echo %AZ_BATCH_TASK_ID% >> " + taskOutputFile; // The job release task will then delete the text file from the shared directory const string jobReleaseCmdLine = "cmd /c del " + taskOutputFile; // Configure your AccountSettings in the Microsoft.Azure.Batch.Samples.Common project within this solution BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(AccountSettings.Default.BatchServiceUrl, AccountSettings.Default.BatchAccountName, AccountSettings.Default.BatchAccountKey); // Initialize the BatchClient for access to your Batch account using (BatchClient batchClient = await BatchClient.OpenAsync(cred)) { // Create a CloudPool (or obtain an existing pool with the specified ID) CloudPool pool = await ArticleHelpers.CreatePoolIfNotExistAsync(batchClient, poolId, "small", 2, 1); // Create a CloudJob (or obtain an existing job with the specified ID) CloudJob job = await SampleHelpers.GetJobIfExistAsync(batchClient, jobId); if (job == null) { Console.WriteLine("Job {0} not found, creating...", jobId); CloudJob unboundJob = batchClient.JobOperations.CreateJob(jobId, new PoolInformation() { PoolId = poolId }); // Configure and assign the job preparation task unboundJob.JobPreparationTask = new JobPreparationTask { CommandLine = jobPrepCmdLine }; // Configure and assign the job release task unboundJob.JobReleaseTask = new JobReleaseTask { CommandLine = jobReleaseCmdLine }; await unboundJob.CommitAsync(); // Get the bound version of the job with all of its properties populated job = await batchClient.JobOperations.GetJobAsync(jobId); } // Create the tasks that the job will execute List <CloudTask> tasks = new List <CloudTask>(); for (int i = 1; i <= 8; i++) { string taskId = "task" + i.ToString().PadLeft(3, '0'); string taskCommandLine = taskCmdLine; CloudTask task = new CloudTask(taskId, taskCommandLine); tasks.Add(task); } // Add the tasks in one API call as opposed to a separate AddTask call for each. Bulk task // submission helps to ensure efficient underlying API calls to the Batch service. Console.WriteLine("Submitting tasks and awaiting completion..."); await batchClient.JobOperations.AddTaskAsync(job.Id, tasks); // Wait for the tasks to complete before proceeding. The long timeout here is to allow time // for the nodes within the pool to be created and started if the pool had not yet been created. if (await batchClient.Utilities.CreateTaskStateMonitor().WhenAllAsync(job.ListTasks(), TaskState.Completed, TimeSpan.FromMinutes(30))) { Console.WriteLine("Operation timed out while waiting for submitted tasks to reach state {0}", TaskState.Completed); return; } else { Console.WriteLine("All tasks completed."); Console.WriteLine(); } // Print the contents of the shared text file modified by the job preparation and other tasks. ODATADetailLevel nodeDetail = new ODATADetailLevel(selectClause: "id, state"); IPagedEnumerable <ComputeNode> nodes = batchClient.PoolOperations.ListComputeNodes(pool.Id, nodeDetail); await nodes.ForEachAsync(async (node) => { // Check to ensure that the node is Idle before attempting to pull the text file. // If the pool was just created, there is a chance that another node completed all // of the tasks prior to the other node(s) completing their startup procedure. if (node.State == ComputeNodeState.Idle) { NodeFile sharedTextFile = await node.GetNodeFileAsync("shared\\job_prep_and_release.txt"); Console.WriteLine("Contents of {0} on {1}:", sharedTextFile.Name, node.Id); Console.WriteLine("-------------------------------------------"); Console.WriteLine(await sharedTextFile.ReadAsStringAsync()); } }); // Terminate the job to mark it as Completed; this will initiate the Job Release Task on any node // that executed job tasks. Note that the Job Release Task is also executed when a job is deleted, // thus you need not call Terminate if you typically delete your jobs upon task completion. await batchClient.JobOperations.TerminateJobAsync(job.Id); // Wait for the job to reach state "Completed." Note that this wait is not typically necessary in // production code, but is done here to enable the checking of the release tasks exit code below. await ArticleHelpers.WaitForJobToReachStateAsync(batchClient, job.Id, JobState.Completed, TimeSpan.FromMinutes(2)); // Print the exit codes of the prep and release tasks by obtaining their execution info List <JobPreparationAndReleaseTaskExecutionInformation> prepReleaseInfo = await batchClient.JobOperations.ListJobPreparationAndReleaseTaskStatus(job.Id).ToListAsync(); foreach (JobPreparationAndReleaseTaskExecutionInformation info in prepReleaseInfo) { Console.WriteLine(); Console.WriteLine("{0}: ", info.ComputeNodeId); // If no tasks were scheduled to run on the node, the JobPreparationTaskExecutionInformation will be null if (info.JobPreparationTaskExecutionInformation != null) { Console.WriteLine(" Prep task exit code: {0}", info.JobPreparationTaskExecutionInformation.ExitCode); } // If no tasks were scheduled to run on the node, the JobReleaseTaskExecutionInformation will be null if (info.JobReleaseTaskExecutionInformation != null) { Console.WriteLine(" Release task exit code: {0}", info.JobReleaseTaskExecutionInformation.ExitCode); } } // Clean up the resources we've created in the Batch account Console.WriteLine(); Console.WriteLine("Delete job? [yes] no"); string response = Console.ReadLine().ToLower(); if (response != "n" && response != "no") { // Note that deleting the job will execute the job release task if the job was not previously terminated await batchClient.JobOperations.DeleteJobAsync(job.Id); } Console.WriteLine("Delete pool? [yes] no"); response = Console.ReadLine(); if (response != "n" && response != "no") { await batchClient.PoolOperations.DeletePoolAsync(pool.Id); } } }
private static async Task MainAsync() { string poolId = "JobPrepReleaseSamplePool"; string jobId = "JobPrepReleaseSampleJob"; var settings = Config.LoadAccountSettings(); // Location of the file that the job tasks will work with, a text file in the // node's "shared" directory. string taskOutputFile = "$AZ_BATCH_NODE_SHARED_DIR/job_prep_and_release.txt"; // The job prep task will write the node ID to the text file in the shared directory string jobPrepCmdLine = $@"/bin/bash -c ""echo $AZ_BATCH_NODE_ID tasks: > {taskOutputFile}"""; // Each task then echoes its ID to the same text file string taskCmdLine = $@"/bin/bash -c ""echo $AZ_BATCH_TASK_ID >> {taskOutputFile}"""; // The job release task will then delete the text file from the shared directory string jobReleaseCmdLine = $@"/bin/bash -c ""rm {taskOutputFile}"""; BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(settings.BatchServiceUrl, settings.BatchAccountName, settings.BatchAccountKey); using (BatchClient batchClient = BatchClient.Open(cred)) { var pool = await BatchUtils.CreatePoolIfNotExistAsync(batchClient, poolId); var prepTask = new JobPreparationTask { CommandLine = jobPrepCmdLine }; var releaseTask = new JobReleaseTask { CommandLine = jobReleaseCmdLine }; var job = await BatchUtils.CreateJobIfNotExistAsync(batchClient, pool.Id, jobId, prepTask : prepTask, releaseTask : releaseTask); // Create the tasks that the job will execute List <CloudTask> tasks = new List <CloudTask>(); for (int i = 1; i <= 8; i++) { string taskId = "task" + i.ToString().PadLeft(3, '0'); string taskCommandLine = taskCmdLine; CloudTask task = new CloudTask(taskId, taskCommandLine); tasks.Add(task); } // Add the tasks in one API call as opposed to a separate AddTask call for each. Bulk task // submission helps to ensure efficient underlying API calls to the Batch service. Console.WriteLine("Submitting tasks and awaiting completion..."); await batchClient.JobOperations.AddTaskAsync(job.Id, tasks); // Wait for the tasks to complete before proceeding. The long timeout here is to allow time // for the nodes within the pool to be created and started if the pool had not yet been created. await batchClient.Utilities.CreateTaskStateMonitor().WhenAll( job.ListTasks(), TaskState.Completed, TimeSpan.FromMinutes(30)); Console.WriteLine("All tasks completed."); Console.WriteLine(); // Print the contents of the shared text file modified by the job preparation and other tasks. ODATADetailLevel nodeDetail = new ODATADetailLevel(selectClause: "id, state"); IPagedEnumerable <ComputeNode> nodes = batchClient.PoolOperations.ListComputeNodes(poolId, nodeDetail); await nodes.ForEachAsync(async (node) => { // Check to ensure that the node is Idle before attempting to pull the text file. // If the pool was just created, there is a chance that another node completed all // of the tasks prior to the other node(s) completing their startup procedure. if (node.State == ComputeNodeState.Idle) { var files = await node.ListNodeFiles().ToListAsync(); NodeFile sharedTextFile = await node.GetNodeFileAsync("shared/job_prep_and_release.txt"); Console.WriteLine("Contents of {0} on {1}:", sharedTextFile.Path, node.Id); Console.WriteLine("-------------------------------------------"); Console.WriteLine(await sharedTextFile.ReadAsStringAsync()); } }); // Terminate the job to mark it as Completed; this will initiate the Job Release Task on any node // that executed job tasks. Note that the Job Release Task is also executed when a job is deleted, // thus you need not call Terminate if you typically delete your jobs upon task completion. await batchClient.JobOperations.TerminateJobAsync(job.Id); // Wait for the job to reach state "Completed." Note that this wait is not typically necessary in // production code, but is done here to enable the checking of the release tasks exit code below. await BatchUtils.WaitForJobToReachStateAsync(batchClient, job.Id, JobState.Completed, TimeSpan.FromMinutes(2)); // Print the exit codes of the prep and release tasks by obtaining their execution info List <JobPreparationAndReleaseTaskExecutionInformation> prepReleaseInfo = await batchClient.JobOperations.ListJobPreparationAndReleaseTaskStatus(job.Id).ToListAsync(); foreach (JobPreparationAndReleaseTaskExecutionInformation info in prepReleaseInfo) { Console.WriteLine(); Console.WriteLine("{0}: ", info.ComputeNodeId); // If no tasks were scheduled to run on the node, the JobPreparationTaskExecutionInformation will be null if (info.JobPreparationTaskExecutionInformation != null) { Console.WriteLine(" Prep task exit code: {0}", info.JobPreparationTaskExecutionInformation.ExitCode); } // If no tasks were scheduled to run on the node, the JobReleaseTaskExecutionInformation will be null if (info.JobReleaseTaskExecutionInformation != null) { Console.WriteLine(" Release task exit code: {0}", info.JobReleaseTaskExecutionInformation.ExitCode); } } // Clean up the resources we've created in the Batch account Console.WriteLine(); Console.WriteLine("Delete job? [yes] no"); string response = Console.ReadLine().ToLower(); if (response != "n" && response != "no") { // Note that deleting the job will execute the job release task if the job was not previously terminated await batchClient.JobOperations.DeleteJobAsync(job.Id); } Console.WriteLine("Delete pool? [yes] no"); response = Console.ReadLine(); if (response != "n" && response != "no") { await batchClient.PoolOperations.DeletePoolAsync(poolId); } } }
private static async Task MainAsync() { const int nodeCount = 1; string poolId = "TaskDependenciesSamplePool"; string jobId = "TaskDependenciesJob"; var settings = Config.LoadAccountSettings(); BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(settings.BatchServiceUrl, settings.BatchAccountName, settings.BatchAccountKey); using (BatchClient batchClient = BatchClient.Open(cred)) { var pool = await BatchUtils.CreatePoolIfNotExistAsync(batchClient, poolId, lowPriorityNodes : nodeCount); var job = await BatchUtils.CreateJobIfNotExistAsync(batchClient, pool.Id, jobId, usesTaskDependencies : true); string taskOutputFile = "$AZ_BATCH_NODE_SHARED_DIR/task_output.txt"; // Create the collection of tasks that will be added to the job. List <CloudTask> tasks = new List <CloudTask> { // 'Rain' and 'Sun' don't depend on any other tasks new CloudTask("Rain", $"/bin/bash -c \"echo Rain >> {taskOutputFile}\""), new CloudTask("Sun", $"/bin/bash -c \"echo Sun >> {taskOutputFile}\""), // Task 'Flowers' depends on completion of both 'Rain' and 'Sun' // before it is run. new CloudTask("Flowers", $"/bin/bash -c \"echo Flowers >> {taskOutputFile}\"") { DependsOn = TaskDependencies.OnIds("Rain", "Sun") }, // Tasks 1, 2, and 3 don't depend on any other tasks. Because // we will be using them for a task range dependency, we must // specify string representations of integers as their ids. new CloudTask("1", $"/bin/bash -c \"echo 1 >> {taskOutputFile}\""), new CloudTask("2", $"/bin/bash -c \"echo 2 >> {taskOutputFile}\""), new CloudTask("3", $"/bin/bash -c \"echo 3 >> {taskOutputFile}\""), // Task dependency on ID range new CloudTask("Final", $"/bin/bash -c \"echo Final >> {taskOutputFile}\"") { DependsOn = TaskDependencies.OnIdRange(1, 3) }, // Task A is the parent task. new CloudTask("A", $"/bin/bash -c \"echo A >> {taskOutputFile}\"") { // Specify exit conditions for task A and their dependency actions. ExitConditions = new ExitConditions { // If task A exits with a pre-processing error, block any downstream tasks (in this example, task B). PreProcessingError = new ExitOptions { DependencyAction = DependencyAction.Block }, // If task A exits with the specified error codes, block any downstream tasks (in this example, task B). ExitCodes = new List <ExitCodeMapping> { new ExitCodeMapping(10, new ExitOptions() { DependencyAction = DependencyAction.Block }), new ExitCodeMapping(20, new ExitOptions() { DependencyAction = DependencyAction.Block }) }, // If task A succeeds or fails with any other error, any downstream tasks become eligible to run // (in this example, task B). Default = new ExitOptions { DependencyAction = DependencyAction.Satisfy }, } }, // Task B depends on task A. Whether it becomes eligible to run depends on how task A exits. new CloudTask("B", $"/bin/bash -c \"echo B >> {taskOutputFile}\"") { DependsOn = TaskDependencies.OnId("A") }, }; // Add the tasks in one API call as opposed to a separate AddTask call for each. Bulk task // submission helps to ensure efficient underlying API calls to the Batch service. Console.WriteLine("Submitting tasks and awaiting completion..."); await batchClient.JobOperations.AddTaskAsync(job.Id, tasks); // Wait for the tasks to complete before proceeding. The long timeout here is to allow time // for the nodes within the pool to be created and started if the pool had not yet been created. await batchClient.Utilities.CreateTaskStateMonitor().WhenAll( job.ListTasks(), TaskState.Completed, TimeSpan.FromMinutes(30)); Console.WriteLine("All tasks completed."); Console.WriteLine(); // Print the contents of the shared text file modified by the job preparation and other tasks. ODATADetailLevel nodeDetail = new ODATADetailLevel(selectClause: "id, state"); IPagedEnumerable <ComputeNode> nodes = batchClient.PoolOperations.ListComputeNodes(poolId, nodeDetail); await nodes.ForEachAsync(async (node) => { // Check to ensure that the node is Idle before attempting to pull the text file. // If the pool was just created, there is a chance that another node completed all // of the tasks prior to the other node(s) completing their startup procedure. if (node.State == ComputeNodeState.Idle) { NodeFile sharedTextFile = await node.GetNodeFileAsync("shared/task_output.txt"); Console.WriteLine("Contents of {0} on {1}:", sharedTextFile.Path, node.Id); Console.WriteLine("-------------------------------------------"); Console.WriteLine(await sharedTextFile.ReadAsStringAsync()); } }); // Clean up the resources we've created in the Batch account Console.WriteLine(); Console.WriteLine("Delete job? [yes] no"); string response = Console.ReadLine().ToLower(); if (response != "n" && response != "no") { // Note that deleting the job will execute the job release task if the job was not previously terminated await batchClient.JobOperations.DeleteJobAsync(job.Id); } Console.WriteLine("Delete pool? [yes] no"); response = Console.ReadLine(); if (response != "n" && response != "no") { await batchClient.PoolOperations.DeletePoolAsync(poolId); } } }