public static async Task UploadDirectoryAsync(this IHosting hosting, DirectoryInfo source, UPath destination, IProgress <UPath> failures = null, IProgress <UPath> successes = null, Action <UPath, Exception> logger = null) { if (!await hosting.IsDirectoryAsync(destination.Parent)) { throw new UnexpectedItemType("Parent of destination should be directory"); } if (await hosting.IsFileAsync(destination)) { throw new UnexpectedItemType("Destination should be a directory"); } await hosting.MakeDirectoryAsync(destination); var tasks = new List <Task>(); foreach (var directory in source.GetDirectories()) { var d = destination.SubPath(directory.Name); var task = hosting.UploadDirectoryAsync(directory, d, failures, successes, logger); tasks.Add(task.ContinueWith(t => { (t.IsFaulted ? failures : successes).Report(d); if (t.IsFaulted) { logger(d, t.Exception.InnerException); } })); } foreach (var file in source.GetFiles()) { var f = destination.SubPath(file.Name); var task = hosting.UploadFileAsync(file, f); tasks.Add(task.ContinueWith(t => { (t.IsFaulted ? failures : successes).Report(f); if (t.IsFaulted) { logger(f, t.Exception.InnerException); } })); } await Task.WhenAll(tasks); }