/// <summary> /// See <see cref="IFileStagingProvider.StageFilesAsync"/>. /// </summary> /// <param name="filesToStage">The instances of IFileStagingProvider to stage.</param> /// <param name="fileStagingArtifact">IFileStagingProvider specific staging artifacts including error/progress.</param> /// <returns>A <see cref="Task"/> object that represents the asynchronous operation.</returns> public async Task StageFilesAsync(List <IFileStagingProvider> filesToStage, IFileStagingArtifact fileStagingArtifact) { Task taskForStaticStaging = FileToStage.StageFilesInternalAsync(filesToStage, fileStagingArtifact); await taskForStaticStaging.ConfigureAwait(continueOnCapturedContext : false); return; }
/// <summary> /// Starts an asynchronous call to stage the given files. /// </summary> private static async System.Threading.Tasks.Task StageFilesInternalAsync(List <IFileStagingProvider> filesToStage, IFileStagingArtifact fileStagingArtifact) { if (null == filesToStage) { throw new ArgumentNullException("filesToStage"); } if (null == fileStagingArtifact) { throw new ArgumentNullException("filesStagingArtifact"); } SequentialFileStagingArtifact seqArtifact = fileStagingArtifact as SequentialFileStagingArtifact; if (null == seqArtifact) { throw new ArgumentOutOfRangeException(ErrorMessages.FileStagingIncorrectArtifact); } // is there any work to do? if (null == FindAtLeastOne(filesToStage)) { return; // now work to do. none of the files belong to this provider } // is there any work to do if ((null == filesToStage) || (filesToStage.Count <= 0)) { return; // we are done } // create a Run task to create the blob containers if needed System.Threading.Tasks.Task createContainerTask = System.Threading.Tasks.Task.Run(() => { CreateDefaultBlobContainerAndSASIfNeededReturn(filesToStage, seqArtifact); }); // wait for container to be created await createContainerTask.ConfigureAwait(continueOnCapturedContext : false); // begin staging the files System.Threading.Tasks.Task stageTask = StageFilesAsync(filesToStage, seqArtifact); // wait for files to be staged await stageTask.ConfigureAwait(continueOnCapturedContext : false); }
internal static async System.Threading.Tasks.Task StageFilesAsync(List <IFileStagingProvider> filesToStage, ConcurrentDictionary <Type, IFileStagingArtifact> allFileStagingArtifacts, string namingFragment) { try { if (null == allFileStagingArtifacts) { throw new ArgumentNullException("allFileStagingArtifacts"); } if (allFileStagingArtifacts.Count > 0) { throw new ArgumentOutOfRangeException("allFileStagingArtifacts.Count"); } // first we get the buckets. One for each file staging provider that contains only the files for that provider. Dictionary <Type, List <IFileStagingProvider> > bucketByProviders = BucketizeFileStagingProviders(filesToStage); // missing artifacts will be instantiated and stored here temporarily Dictionary <Type, IFileStagingArtifact> pendingArtifactsToAdd = new Dictionary <Type, IFileStagingArtifact>(); // detect any missing staging artifacts. Each bucket must have a staging artifact. foreach (Type curProviderType in bucketByProviders.Keys) { IFileStagingArtifact curProviderArtifact; // if no artifact was passed in, instantiate one and have it added if (!allFileStagingArtifacts.TryGetValue(curProviderType, out curProviderArtifact)) { // we need to have the staging provider create an artifact instance // so first we retrieve the list of files and ask one of them List <IFileStagingProvider> filesForProviderType; if (bucketByProviders.TryGetValue(curProviderType, out filesForProviderType)) { Debug.Assert(filesForProviderType.Count > 0); // to be in a bucket means there must be at least one. IFileStagingProvider curProviderAsInterface = filesForProviderType[0]; IFileStagingArtifact newArtifactFreshFromProvider = curProviderAsInterface.CreateStagingArtifact(); // give the file stager the naming fragment if it does not already have one by default if (string.IsNullOrEmpty(newArtifactFreshFromProvider.NamingFragment) && !string.IsNullOrEmpty(namingFragment)) { newArtifactFreshFromProvider.NamingFragment = namingFragment; } pendingArtifactsToAdd.Add(curProviderType, newArtifactFreshFromProvider); } } } // add missing artifacts to collection foreach (Type curProvderType in pendingArtifactsToAdd.Keys) { IFileStagingArtifact curArtifact; if (pendingArtifactsToAdd.TryGetValue(curProvderType, out curArtifact)) { allFileStagingArtifacts.TryAdd(curProvderType, curArtifact); } } // now we have buckets of files for each provider and artifacts for each provider // start tasks for each provider // list of all running providers List <System.Threading.Tasks.Task> runningProviders = new List <System.Threading.Tasks.Task>(); // start a task for each FileStagingProvider foreach (List <IFileStagingProvider> curProviderFilesToStage in bucketByProviders.Values) { Debug.Assert(curProviderFilesToStage.Count > 0); IFileStagingProvider anyInstance = curProviderFilesToStage[0]; // had to be at least one to get here. System.Threading.Tasks.Task providerTask; // this is the async task for this provider IFileStagingArtifact stagingArtifact; // artifact for this provider if (allFileStagingArtifacts.TryGetValue(anyInstance.GetType(), out stagingArtifact)) // register the staging artifact { providerTask = anyInstance.StageFilesAsync(curProviderFilesToStage, stagingArtifact); runningProviders.Add(providerTask); } else { Debug.Assert(true, "The staging artifacts collection is somehow missing an artifact for " + anyInstance.GetType().ToString()); } } // // the individual tasks were created above // now a-wait for them all to finish // System.Threading.Tasks.Task[] runningArray = runningProviders.ToArray(); System.Threading.Tasks.Task allRunningTasks = System.Threading.Tasks.Task.WhenAll(runningArray); // actual a-wait for all the providers await allRunningTasks.ConfigureAwait(continueOnCapturedContext : false); } catch (Exception ex) { if (null != ex) { throw; // TODO: trace here? } } }