Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 一种多线程文件处理方法_.net_Multithreading_Stream_Thread Safety_Producer Consumer - Fatal编程技术网

.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
      • 等待所有任务完成
      • 最后读取这些临时文件并按顺序创建输出文件
      • 然后当然删除那些临时文件。你完了
      是否可以选择向用于在内存中保存区块数据的结构添加索引?读卡器将按顺序填充,写卡器将等待下一个块写入。作为数据结构,我只需要使用一个分块排序的集合。@AdrianoRepetti我的处理是无顺序完成的,所以我需要在编写之前进行排序,这就是我存储索引的原因。添加和删除阻塞已排序集合的复杂性有多大?每次添加后是否对元素进行排序?处理是否耗时?或者它会很快完成?这取决于它是如何实现的。一般来说,我会使用单链表,但这取决于具体的时间场景。即使是一个未排序的集合+一个用于存储最新接收到的数据包索引的支持变量也可能起作用(在这种情况下,您的插入性能更好,但写入性能更差,顺便说一句,涉及I/O的I不会在意)。@SriramSakthivel,如果处理很快完成会更好=)是否可以向用于将块数据保留在内存中的结构添加索引?读卡器将按顺序填充,写卡器将等待下一个块写入。作为数据结构,我只需要使用一个分块排序的集合。@AdrianoRepetti我的处理是无顺序完成的,所以我需要在编写之前进行排序,这就是我存储索引的原因。添加和删除阻塞已排序集合的复杂性有多大?每次添加后是否对元素进行排序?处理是否耗时?或者它会很快完成?这取决于它是如何实现的。一般来说,我会使用单链表,但我