我正在扫描一些目录中的项目。我刚读过
Multithreaded Directory Looping in C#
问题,但我还是想让它成为多重的。尽管每个人都说驱动器将成为瓶颈,但我有一些观点:
-
这些驱动器可能大多是“单线程”的,但您如何知道它们将来会带来什么呢?
-
如何知道正在扫描的不同子路径是同一个物理驱动器?
-
我使用一个抽象层(甚至两个)覆盖
System.IO
这样我以后可以在不同的场景中重用代码。
任务
第一个虚拟实现是:
public async Task Scan(bool recursive = false) {
var t = new Task(() => {
foreach (var p in path.scan) Add(p);
if (!recursive) return;
var tks = new Task[subs.Count]; var i = 0;
foreach (var s in subs) tks[i++] = s.Scan(true);
Task.WaitAll(tks);
}); t.Start();
await t;
}
我不喜欢创建一个
Task
这种方法有效,但速度很慢。这需要更多的时间
以完成,而下面的单一威胁版本将
0.5s
要在同一数据集上完成整个程序:
public void Scan2(bool recursive = false) {
foreach (var p in path.scan) Add(p);
if (!recursive) return;
foreach (var s in subs) s.Scan2(true);
}
我不知道拳头法到底出了什么问题。机器没有负载,杯子使用量很小,驱动很好。。。我试着用NProfiler分析它,除了程序本身,它不会告诉我太多
Task.WaitAll(tks)
我还编写了一个线程锁定计数机制,在添加每个项时调用该机制。也许是它的问题?
#region SubCouting
public Dictionary<Type, int> counters = new Dictionary<Type, int>();
private object cLock = new object();
private int _sc = 0;
public int subCount => _sc;
private void inCounter(Type t) {
lock (cLock) {
if (!counters.ContainsKey(t)) counters.Add(t, 1);
counters[t]++;
_sc++;
}
if (parent) parent.inCounter(t);
}
#endregion
但是,即使线程在这里等待,执行时间是否会与单线程版本类似,而不是慢10倍?
我不知道该怎么做。如果我不想使用任务,我是否需要手动管理线程,或者是否已经有一些库可以很好地适合这项工作?