在每次大while循环迭代时创建任务是否存在性能和/或安全问题

本文关键字:性能 存在 是否 问题 安全 任务 创建 while 循环 迭代 | 更新日期: 2023-09-27 18:02:44

我正在查询一个数据库并检索数十万条记录。然后读取返回的SqlReader,并为每条记录创建一个新任务。然后,新任务执行一些长时间运行的操作。

我的代码看起来有点像这样:

    void ProcessRecords(SqlDataReader reader)
    {
        if (!reader.HasRows)
        {
            return;
        }
        using (reader)
        {
            while (reader.Read())
            {
                var filePath = BuildFilePath(reader);
                var imageId = (int)reader["PhotoID"];
                Task.Run(() => { ProcessRecord(imageId, filePath); })
                    .ContinueWith((task) => { Progress.Report("Processing " + Path.GetFileName(filePath)); });
            }
        }
    }

一位高级开发人员建议我使用信号量来限制任务使用的线程数。这是解决问题的正确方法吗?

在每次大while循环迭代时创建任务是否存在性能和/或安全问题

问题总是,

对于并行所做的单位工作,并行需要多少开销?

这取决于管理并行性的开销和完成的工作量。

一般来说,廉价的并行需要几十到几百条指令来分叉一个并行工作单元。这意味着要做的工作必须是数千条指令,以允许并行开销被正在完成的实际工作所支配。

如果

操作笨拙(例如,"创建一个线程"),"并行性"的代价会大得多,因为创建线程并不便宜。大多数计算都不够昂贵,不足以证明这样做是合理的。

OP的例子可能是非常罕见的情况,它可能是有意义的:对磁盘执行一些事务,如果磁头必须移动,则需要数十毫秒。

一般来说,对磁盘驱动器进行并行I/O是行不通的;它只有一个磁头,因此对磁盘的并行操作是序列化的,不会重叠。

如果"ProcessRecord"时间占磁盘时间,则此代码可能有效。(当然,OP已经衡量了他的计划,看看它有多有效?)在这种情况下,将活动线程的数量限制为cpu数量的若干倍可能会获得尽可能多的并行性,而不需要消耗千兆字节的内存来跟踪长文件列表可能提供的数万个线程(如果您的操作系统甚至会这样做)。