.net 一种多线程文件处理方法
我有一个相当大的文件(.net 一种多线程文件处理方法,.net,multithreading,stream,thread-safety,producer-consumer,.net,Multithreading,Stream,Thread Safety,Producer Consumer,我有一个相当大的文件(>15GB)(不管是什么类型的文件)。 我必须读取文件,对数据进行一些处理,然后将处理后的数据写入空白文件。 我分块做。每个块都包含某种类型的头,后面是数据。多个区块中最简单的文件将包含: Number of block bytes Block bytes Number of block bytes Block bytes 所以,我创建了一个线程,用于逐块读取文件,一些线程用于处理每个读取的块,还有一个线程用于按块写入已处理的数据 我在管理线程方面有点问题 我不知道每个块
>15GB
)(不管是什么类型的文件)。
我必须读取文件,对数据进行一些处理,然后将处理后的数据写入空白文件。
我分块做。每个块都包含某种类型的头,后面是数据。多个区块中最简单的文件将包含:
Number of block bytes
Block bytes
Number of block bytes
Block bytes
所以,我创建了一个线程,用于逐块读取文件,一些线程用于处理每个读取的块,还有一个线程用于按块写入已处理的数据
我在管理线程方面有点问题
我不知道每个块的处理顺序,尽管我必须按照读取顺序将块写入文件
所以,我的问题是,我必须使用什么样的方法来管理多线程处理
我想,如果我使用producer-nancemer模式,可能会更好。在这种情况下,存储已处理数据的最佳数据结构是什么?我有一个猜测——一个基于数组的堆栈,在开始编写之前需要排序一次
但我不确定。所以,请帮我一个方法
//sample of my code, but without any logic of threads managing
public class DataBlock
{
public byte[] Data { get; }
public long Index { get; }
public DataBlock(byte[] data, long index)
{
this.Data = data;
this.Index = index;
}
}
int bufferSize = 1024*64; //65536
long processedBlockCounter = 0L;
MyStack<DataBlock> processedBlockStore = new MyStack<DataBlock>();
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize))
{
using (BufferedStream bs = new BufferedStream(fs, bufferSize))
{
byte[] buffer = new byte[bufferSize];
int byteRead;
while ((byteRead = bs.Read(buffer, 0, bufferSize)) > 0)
{
byte[] originalBytes;
using (MemoryStream mStream = new MemoryStream())
{
mStream.Write(buffer, 0, byteRead);
originalBytes = mStream.ToArray();
}
long dataBlockIndex = Interlocked.Increment(ref processedBlockCounter);
Thread processThread = new Thread(() =>
{
byte[] processedBytes = MyProcessor.Process(originalBytes);
DataBlock processedBlock = new DataBlock(processedBytes, processedBlockCounter);
lock(processedBlockStore)
{
processedBlockStore.Add(processedBlock);
}
});
processThread.Start();
}
}
}
//我的代码示例,但没有任何线程管理逻辑
公共类数据块
{
公共字节[]数据{get;}
公共长索引{get;}
公共数据块(字节[]数据,长索引)
{
这个。数据=数据;
这个。索引=索引;
}
}
int bufferSize=1024*64//65536
长处理块计数器=0L;
MyStack processedBlockStore=new MyStack();
使用(FileStream fs=newfilestream(路径,FileMode.Open,FileAccess.Read,FileShare.Read,bufferSize))
{
使用(BufferedStream bs=新的BufferedStream(fs,bufferSize))
{
字节[]缓冲区=新字节[bufferSize];
内特比德;
而((byteRead=bs.Read(buffer,0,bufferSize))>0)
{
字节[]原始字节;
使用(MemoryStream mStream=new MemoryStream())
{
写入(缓冲区,0,字节数);
originalBytes=mStream.ToArray();
}
长数据块索引=联锁增量(ref PROCESSED BLOCKCOUNTER);
线程进程线程=新线程(()=>
{
byte[]processedBytes=MyProcessor.Process(原始字节);
DataBlock processedBlock=新的数据块(processedBytes,processedBlockCounter);
锁(processedBlockStore)
{
processedBlockStore.Add(processedBlock);
}
});
processThread.Start();
}
}
}
您正在为每个迭代创建新线程。这不会扩大规模。我建议您改用ThreadPool。首选的方法是使用TPL,它在内部使用ThreadPool
由于您需要排序和并行处理,而且它们不能同时进行,因此您可以选择使代码完全同步
如果您需要并行处理,我建议您采用以下策略,因为您的文件大于15GB,而且处理也很耗时
- 将文件分块
- 用每个区块启动一个任务
- 使每个任务将输出写入名为index的临时文件
,1.txt
等2.txt
- 等待所有任务完成
- 最后读取这些临时文件并按顺序创建输出文件
- 然后当然删除那些临时文件。你完了李>
- 您正在为每个迭代创建新线程。这不会扩大规模。我建议您改用ThreadPool。首选的方法是使用TPL,它在内部使用ThreadPool
由于您需要排序和并行处理,而且它们不能同时进行,因此您可以选择使代码完全同步
如果您需要并行处理,我建议您采用以下策略,因为您的文件大于15GB,而且处理也很耗时
- 将文件分块
- 用每个区块启动一个任务
- 使每个任务将输出写入名为index的临时文件
,1.txt
等2.txt
- 等待所有任务完成
- 最后读取这些临时文件并按顺序创建输出文件
- 然后当然删除那些临时文件。你完了李>