static Task PostAllFilePathsAsync(IEnumerable<CollectionPath> paths, Func<FileInfo, bool> filePredicate, ITargetBlock<AnnotatedPath> filePathTargetBlock, CancellationToken cancellationToken) { var scanTasks = paths .Select<CollectionPath, Task>(path => Task.Factory.StartNew( async () => { foreach (var file in PathUtil.ScanDirectory(path.Path, filePredicate)) { if (cancellationToken.IsCancellationRequested) break; var relativePath = PathUtil.MakeRelativePath(path.Path, file.FullName); var annotatedPath = new AnnotatedPath { FileInfo = file, Collection = path.Collection ?? path.Path, RelativePath = relativePath }; await filePathTargetBlock.SendAsync(annotatedPath, cancellationToken).ConfigureAwait(false); } }, cancellationToken, TaskCreationOptions.DenyChildAttach | TaskCreationOptions.LongRunning | TaskCreationOptions.RunContinuationsAsynchronously, TaskScheduler.Default)); var task = Task.WhenAll(scanTasks); var completeTask = task.ContinueWith(_ => filePathTargetBlock.Complete()); TaskCollector.Default.Add(completeTask, "PostAllFilePathsAsync"); return task; }
Task SetAnnotatedPathAsync(AnnotatedPath annotatedPath) { var pathFingerprint = GetPathFingerprint(annotatedPath.FileInfo.FullName); var key = Tuple.Create(annotatedPath.Collection, annotatedPath.RelativePath); IFileFingerprint fileFingerprint; lock (pathFingerprint) { if (pathFingerprint.AnnotatedPaths.ContainsKey(key)) throw new InvalidOperationException("Duplicate collection/relative path for " + annotatedPath.FileInfo.FullName); pathFingerprint.AnnotatedPaths[key] = annotatedPath; fileFingerprint = pathFingerprint.FileFingerprint; } if (null == fileFingerprint) return Task.CompletedTask; return _targetBlock.SendAsync(Tuple.Create(annotatedPath, fileFingerprint)); }