c# - 读取大量文件 "at the same time"

标签 c# io

我使用FileSystemWatcher来捕获每个创建更改删除重命名更改文件夹中的任何文件。

对于这些更改,我需要对这些文件的内容执行简单的校验和。简而言之,我打开一个文件流并将其传递给 MD5 类:

private byte[] calculateChecksum(string frl)
{
    using (FileStream stream = File.Open(frl, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    {
        return this.md5.ComputeHash(stream);
    }
}

问题在于我需要处理的文件数量。例如,假设我在一个文件夹中创建了 200 个文件,然后我将所有文件复制并粘贴到同一个文件夹中。此操作将导致 200 个事件和 200 个 calculateChecksum() 执行。

如何解决此类问题?

最佳答案

FileSystemWatcher处理程序中将任务放入将由某些工作人员处理的队列中。工作人员可以以目标速度或/和频率处理校验和计算任务。可能一名工作人员会更好,因为许多读者可以通过多次读取搜索来减慢硬盘驱动器的速度。

尝试阅读有关 BlockingCollection 的内容: https://msdn.microsoft.com/ru-ru/library/dd997371(v=vs.110).aspx

和生产者-消费者数据流模式 https://msdn.microsoft.com/ru-ru/library/hh228601(v=vs.110).aspx

var workerCount = 2;
BlockingCollection<String>[] filesQueues= new BlockingCollection<String>[workerCount];

for(int i = 0; i < workerCount; i++)
{
    filesQueues[i] = new BlockingCollection<String>(500);

    // Worker
    Task.Run(() => 
    {
        while (!filesQueues[i].IsCompleted)
        {
            string url;

            try
            {
                url= filesQueues[i].Take();
            }
            catch (InvalidOperationException) { }

            if (!string.IsNullOrWhiteSpace(url))
            {
                calculateChecksum(url);
            }
        }
    }
}

//FileSystemWatcher 处理程序内部

    var queueIndex = hash(filename) % workersCount
    // Warning!!
    // Blocks if numbers.Count == dataItems.BoundedCapacity
    filesQueues[queueIndex].Add(fileName);
    filesQueues[queueIndex].CompleteAdding();

您还可以创建多个消费者,只需同时调用 Take 或 TryTake - 每个项目只会被一个消费者消费。但请考虑到,在这种情况下,一个文件可以由多个工作人员处理,并且多个硬盘读取器可能会减慢硬盘速度。

UPD 如果有多个工作人员,最好创建多个 BlockingCollections,并将文件推送到索引为的队列中:

关于c# - 读取大量文件 "at the same time",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34062860/

相关文章:

java - 通过发送套接字发送但从未被接收套接字读取的消息会发生什么?

python - 在 pandas 中读取文本文件,分隔符作为换行符 (\n),行终止符作为两个换行符 (\n\n)

go - 在goroutine中将字符串写入文件

c# - 为什么在搜索具有 OptionSetValue 属性的实体时必须使用 int,而在创建实体时必须使用 OptionSetValue 对象?

c# - 需要在 Asp.net 中创建日期选择器?

c# - 在单例范围内注入(inject) Memoize 实例

C# - 使用单个键从文本文件中获取多个值

C++ 编写代码

c# - 在 Mvc.Controller 中使用服务器

c# - RestSharp JSON 数组反序列化