如果您的代码的目的是使用某种并行性遍历目录结构,那么我建议不要使用 TPL Dataflow 并使用 Microsoft 的 Reactive Framework。我认为事情变得简单多了。
我就是这样做的。
首先定义一个递归函数来构建目录列表:
Func<DirectoryInfo, IObservable<DirectoryInfo>> recurse = null;
recurse = di =>
Observable
.Return(di)
.Concat(di.GetDirectories()
.ToObservable()
.SelectMany(di2 => recurse(di2)))
.ObserveOn(Scheduler.Default);
这会执行目录的递归并使用默认的 Rx 调度程序,这会导致可观察对象并行运行。
所以通过调用recurse
有输入DirectoryInfo
我得到了输入目录及其所有子目录的可观察列表。
现在我可以构建一个相当直接的查询来获得我想要的结果:
var query =
from di in recurse(new DirectoryInfo(@"C:\dev\kortforsyningen_dsm\tiles"))
from fi in di.GetFiles().ToObservable()
let zxy =
fi
.FullName
.Split('\\')
.Reverse()
.Take(3)
.Reverse()
.Select(s => int.Parse(Path.GetFileNameWithoutExtension(s)))
.ToArray()
let suffix = String.Format("{0}/{1}/{2}.png", zxy[0], zxy[1], zxy[2])
select new FileInfo(Path.Combine(di.FullName, suffix));
现在我可以像这样操作查询:
query
.Subscribe(s =>
{
Trace.TraceInformation("Done combining : {0}", s.Name);
});
现在我可能在您的自定义代码中遗漏了一些内容,但如果这是您想要采用的方法,我相信您可以很容易地解决任何逻辑问题。
当子目录和文件用完时,此代码会自动处理完成。
要将 Rx 添加到项目中,请在 NuGet 中查找“Rx-Main”。