Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.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
C# 使用多个BlockingCollection<;T>;实现管道验证的缓冲区_C#_Multithreading_Parallel Processing_Task - Fatal编程技术网

C# 使用多个BlockingCollection<;T>;实现管道验证的缓冲区

C# 使用多个BlockingCollection<;T>;实现管道验证的缓冲区,c#,multithreading,parallel-processing,task,C#,Multithreading,Parallel Processing,Task,因此,我需要读取大型数据文件的每条记录(行),然后在每一行上应用各种验证规则。因此,我决定不只是应用顺序验证,而是看看是否可以使用一些管道来帮助加快速度。因此,我需要对集合中的所有项应用相同的一组业务验证规则(目前为5条)。由于不需要返回每个验证过程的输出,所以我不需要担心将值从一个验证例程传递到另一个验证例程。但是,我确实需要使相同的数据可用于所有验证步骤,为此,我将相同的数据(记录)处理到5个不同的缓冲区,每个验证阶段都将使用这些缓冲区 下面是我的代码。但我对这一点没有信心,我想知道是否有更

因此,我需要读取大型数据文件的每条记录(行),然后在每一行上应用各种验证规则。因此,我决定不只是应用顺序验证,而是看看是否可以使用一些管道来帮助加快速度。因此,我需要对集合中的所有项应用相同的一组业务验证规则(目前为5条)。由于不需要返回每个验证过程的输出,所以我不需要担心将值从一个验证例程传递到另一个验证例程。但是,我确实需要使相同的数据可用于所有验证步骤,为此,我将相同的数据(记录)处理到5个不同的缓冲区,每个验证阶段都将使用这些缓冲区

下面是我的代码。但我对这一点没有信心,我想知道是否有更好的方法?我很感激你能在这方面提供的任何帮助。提前谢谢

public static void LoadBuffers(List<BlockingCollection<FlattenedLoadDetail>> outputs,
            BlockingCollection<StudentDetail> students)
        {
            try
            {
                foreach (var student in students)
                {
                    foreach (var stub in student.RecordYearDetails)
                        foreach (var buffer in outputs)
                            buffer.Add(stub);
                }
            }
            finally
            {
                 foreach (var buffer in outputs)
                     buffer.CompleteAdding();
            }

        }


    public void Process(BlockingCollection<StudentRecordDetail> StudentRecords)
    {

        //Validate header record before proceeding

        if(! IsHeaderRecordValid)
            throw new Exception("Invalid Header Record Found.");
        const int buffersize = 20;
        var buffer1 = new BlockingCollection<FlattenedLoadDetail>(buffersize);
        var buffer2 = new BlockingCollection<FlattenedLoadDetail>(buffersize);
        var buffer3 = new BlockingCollection<FlattenedLoadDetail>(buffersize);
        var buffer4 = new BlockingCollection<FlattenedLoadDetail>(buffersize);
        var taskmonitor = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.NotOnCanceled);

        using (var loadUpStartBuffer = taskmonitor.StartNew(() => LoadBuffers(
            new List<BlockingCollection<FlattenedLoadDetail>>
            {buffer1, buffer2, buffer3, buffer4}, StudentRecords)))
        {
            var recordcreateDateValidationStage = taskmonitor.StartNew(() => ValidateRecordCreateDateActivity.Validate(buffer1));
            var uniqueStudentIDValidationStage =
                taskmonitor.StartNew(() => ValidateUniqueStudentIDActivity.Validate(buffer2));
            var SSNNumberRangeValidationStage =
                taskmonitor.StartNew(() => ValidateDocSequenceNumberActivity.Validate(buffer3));
            var SSNRecordNumberMatchValidationStage =
                taskmonitor.StartNew(() => ValidateStudentSSNRecordNumberActivity.Validate(buffer4));

            Task.WaitAll(loadUpStartBuffer, recordcreateDateValidationStage, uniqueStudentIDValidationStage,
                SSNNumberRangeValidationStage, SSNRecordNumberMatchValidationStage);

        }
    }
publicstaticvoidloadbuffers(列出输出、,
封锁(收集学生)
{
尝试
{
foreach(学生中的var学生)
{
foreach(var存根在student.RecordYearDetails中)
foreach(输出中的var缓冲区)
buffer.Add(存根);
}
}
最后
{
foreach(输出中的var缓冲区)
buffer.CompleteAdding();
}
}
公共作废流程(阻止收集记录)
{
//在继续之前验证标题记录
如果(!IsHeaderRecordValid)
抛出新异常(“找到无效的头记录”);
常量int buffersize=20;
var buffer1=新的BlockingCollection(buffersize);
var buffer2=新的BlockingCollection(buffersize);
var buffer3=新的BlockingCollection(buffersize);
var buffer4=新的BlockingCollection(buffersize);
var taskmonitor=new TaskFactory(TaskCreationOptions.longlunning,TaskContinuationOptions.notincanced);
使用(var loadUpStartBuffer=taskmonitor.StartNew(()=>LoadBuffers(
新名单
{buffer1,buffer2,buffer3,buffer4},StudentRecords)))
{
var recordcreateDateValidationStage=taskmonitor.StartNew(()=>ValidateRecordCreateDateActivity.Validate(buffer1));
var uniqueStudentIDValidationStage=
taskmonitor.StartNew(()=>ValidateUniqueStudentIDActivity.Validate(buffer2));
var SSNNumberRangeValidationStage=
taskmonitor.StartNew(()=>ValidateDocSequenceNumberActivity.Validate(buffer3));
var SSNRecordNumberMatchValidationStage=
taskmonitor.StartNew(()=>validatestudentssnRecordnumeractivity.Validate(buffer4));
Task.WaitAll(loadUpStartBuffer、recordcreateDateValidationStage、uniqueStudentIDValidationStage、,
SSNNumberRangeValidationStage、SSNRecordNumberMatchValidationStage);
}
}

事实上,如果我能以这样一种方式将任务捆绑起来,一旦一个失败,所有其他任务都会停止,这将对我有很大帮助,但我是这种模式的新手,并试图找出处理这个问题的最佳方法。我是否应该将警告抛诸脑后,让每个验证步骤加载一个输出缓冲区以传递给后续任务?这是更好的方法吗

您需要自己回答的第一个问题是,您是想提高延迟还是吞吐量

您描述的策略采用单个项目并对其执行并行计算。这意味着一个项目的服务速度非常快,但牺牲了等待轮到他们进入的其他项目

考虑另一种并行方法。您可以将整个验证过程视为一个顺序操作,但同时并行服务多个项目


在我看来,在您的情况下,您将从后一种方法中受益更多,特别是从简单性的角度来看,因为我猜延迟在这里并不那么重要。

所以您想知道一个项目是否通过了所有5项检查,因为目前您得到的是5个仅通过一项检查的项目列表。这似乎…没那么有用。而且,这里没有多少管道。你将每个项目传递到每个步骤,他们将结果传递到最终结果,仅此而已。管道意味着每个记录都会传递给第一个验证器,然后是第二个,然后是第三个,等等。我的意图是在任何阶段发现无效项时使用TaskContinuation选项来中断。在将数据推送到数据库之前,我需要检查所有项目,以确保它们都通过所有验证阶段。我想在这里通过将相同的项目同时传递到每个验证阶段来加快速度,这样就不用先对项目1执行StageA,然后对项目1执行StageB,然后对项目1执行StageC,依此类推,我可以同时做所有5项,同时对其他每项都做相同的操作。你把问题复杂化了。最好使用多个线程,每个线程对记录子集执行所有五个验证步骤<代码>并行。ForEach可以快速完成这项工作。您提出的解决方案将迫使您编写大量乏味且有点讨厌的代码来整理来自不同线程的结果。但我不需要每个任务的结果。在验证过程中,真正发生的是编译一个不符合规则的记录列表,并将每个记录记录到某个地方的日志文件中。每个验证类上都会更新一个标志,以指示是否找到了不符合规则的记录。如果更新了这些标志中的任何一个,则进程将停止