【问题标题】:Scanning folders via multiple threading通过多线程扫描文件夹
【发布时间】:2021-11-03 13:31:15
【问题描述】:

我正在通过迭代扫描网络驱动器中的文件夹(基本上执行 while 循环)。为了加快进程,我需要为每个文件夹使用线程或任务,并在列表中获得具有属性路径、文件名、lastwriteutc、大小的结果.我在下面做了。

string startFolder = @"D:\Development\TempScan";
string startFolder2 = @"D:\RemotePc";
List<string> foldersToScan = new List<string>();
foldersToScan.Add(startFolder);
foldersToScan.Add(startFolder2);

foreach (var folder in foldersToScan)
{
Thread thread = new Thread(() => IterateFolder(findInfoLevel, additionalFlags, folder))
{
      Name = "Thread " + folder

};

thread.Start();
Console.WriteLine(thread.Name.ToLower() + " has started");
//thread.Join();
}
// Database operation here 

如果我使用thread.Join()方法代码同步,那么只有我可以执行数据库操作,如果我不使用thread.Join(),那么数据库操作将在扫描操作之前被调用。

我也使用了下面的任务,但它也是同步的

Task task1 = Task.Run(() =>
{
foreach (var folder in foldersToScan)
{
IterateFolder(findInfoLevel, additionalFlags, folder);
}
});
task1.Wait(); 

如何实现一个文件夹一个线程的文件夹异步扫描,一旦我得到结果异步数据库插入?

【问题讨论】:

  • @stuartd 你能提供一些参考或示例吗?
  • 查看Parallel.Fortask.WhenAll 而不是手动创建线程。但首先要查看faster file enumeration
  • Task.Run 不是同步的。代码在后台执行。 Wait() 是一个阻塞调用。如果您想同时扫描多个路径,您需要启动多个任务并使用 await Task.WhenAll() 等待所有任务@
  • @JonasH 我使用 win32 API 来迭代文件夹,因为它比 .net 中提供的常规内置函数快 20 倍
  • 不要期望并行运行扫描会有巨大的改进。在并发访问方面,网络驱动器可能会受到网络和磁盘 IO 限制的限制。在全力以赴编码任务之前做一些粗略的测试。

标签: c# multithreading task-parallel-library threadpool bulkinsert


【解决方案1】:
var threads = new List<Thread>();

foreach (var folder in foldersToScan)
{
    var thread = new Thread(() => IterateFolder(findInfoLevel, additionalFlags, folder))
    {
        Name = "Thread " + folder
    };

    thread.Start();
    Console.WriteLine(thread.Name.ToLower() + " has started");
    threads.Add(thread);
}

foreach(var thread in threads)
{
    thread.Join();
}

这样代码会等待/阻塞,直到所有线程都完成。您可以/应该使其更健壮:错误处理、超时或切换到任务。

【讨论】:

  • 它是异步工​​作的 :) 什么技巧 :) 非常感谢,您能否详细说明您在评论中提到的内容,以便在线提供健壮和学习示例 :)
  • var threads = new Thread(() => IterateFolder(findInfoLevel, additionalFlags, folder)) { Name = "Thread " + folder };在上面的代码中只是拼写错误删除线程中的“s”
  • 已修复。谢谢!至于添加改进:thread.Join 可以将超时作为参数,并将返回一个布尔值,指示线程是否在超时内返回。这样您就可以检查它并在 foreach 循环中添加一个 if 。添加异常处理程序(try...catch)也可以在循环中完成。我没有添加这些,因为您如何编写它们在很大程度上取决于程序在这些情况下需要发生什么(重试、恢复、失败、中止),这会分散对原始问题的回答。
【解决方案2】:

你也可以使用 Linq:

foldersToScan.AsParallel().Where( f => IterateFolder( findInfoLevel, additionalFlags, f ) );

Here 是更多关于如何在 Linq 中使用 AsParallel() 的示例。

要使其异步,您可以将其放在一个 BackgroundWorker 或 Thread 中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-16
    • 1970-01-01
    • 2013-05-28
    • 2022-01-06
    • 2016-01-24
    • 2012-03-16
    相关资源
    最近更新 更多