C# TPL数据流管道意外结束

C# TPL数据流管道意外结束,c#,task-parallel-library,C#,Task Parallel Library,我是TPL数据流新手,这是我的第一条管道 我正在将1M行推到EmpresasBuffer。在1000个批次中,EmpresasBuffer将数据发送到SaveBlock,并将其保存到数据库中。保存后,ExitBlock显示到现在为止处理了多少行 这适用于较少的行。如果我尝试推送10000行,它会像预期的那样工作,但是对于1M行,它会默默地失败 检查代码我看到SaveBlock和ExitBlock被设置为Completed,但是,这发生在调用EmpresasBuffer.Complete()之前

我是TPL数据流新手,这是我的第一条管道

我正在将1M行推到
EmpresasBuffer
。在1000个批次中,
EmpresasBuffer
将数据发送到
SaveBlock
,并将其保存到数据库中。保存后,
ExitBlock
显示到现在为止处理了多少行

这适用于较少的行。如果我尝试推送10000行,它会像预期的那样工作,但是对于1M行,它会默默地失败

检查代码我看到
SaveBlock
ExitBlock
被设置为Completed,但是,这发生在调用
EmpresasBuffer.Complete()
之前

这是创建管道的代码:

var EmpresasBuffer = new BatchBlock<EmpresaModel>(1000, 
                        new GroupingDataflowBlockOptions { 
                               EnsureOrdered = false, 
                               BoundedCapacity = 10000 });
var SaveBlock = new TransformBlock<EmpresaModel[], int>(
                        async x => await SalvarEmpresaAsync(x), 
                        new ExecutionDataflowBlockOptions { 
                               EnsureOrdered = false, 
                               MaxDegreeOfParallelism = 32, 
                               BoundedCapacity = 10000 });
car ExitBlock = new ActionBlock<int>(x => {
    Console.WriteLine($"[{DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss")}] Registros Importados: {TotalRows += x}");
});

EmpresasBuffer.LinkTo(SaveBlock, new DataflowLinkOptions { PropagateCompletion = true });
SaveBlock.LinkTo(ExitBlock, new DataflowLinkOptions { PropagateCompletion = true });
我的代码怎么了

这是Salvarempresasync的代码:

public static async Task<int> SalvarEmpresaAsync(EmpresaModel[] modelArray)
{
    using (var Connection = new SqlConnection(ConnectionString))
    {
        Connection.Open();

        var TaskEmpresa = BulkInsert<EmpresaModel>(Connection, "Empresas", modelArray, PropertiesEmpresa);
        var TaskQuadroSocietario = BulkInsert<QuadroSocietarioModel>(Connection, "QuadroSocietario", modelArray.SelectMany(x => x.QuadrosSocietarios).AsEnumerable(), PropertiesQuadroSocietario);

        await TaskEmpresa;
        await TaskQuadroSocietario;
    }


    return modelArray.Length;
}


public static async Task BulkInsert<T>(SqlConnection connection, string tableName, IEnumerable<T> data, string[] columns) where T: class
{
     using (var BulkCopy = new SqlBulkCopy(connection))
     using (var reader = ObjectReader.Create(data, columns))
     {
         foreach (string property in columns)
         {
             BulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping(property, property));
         }

         BulkCopy.DestinationTableName = tableName;
         await BulkCopy.WriteToServerAsync(reader);
     }
 }
公共静态异步任务salvarempresasync(EmpresaModel[]modelArray)
{
使用(var连接=新的SqlConnection(ConnectionString))
{
Connection.Open();
var TaskEmpresa=BulkInsert(连接,“Empresas”、modelArray、PropertiesEmpresa);
var TaskQuadroSocietario=BulkInsert(连接,“QuadroSocietario”,modelArray.SelectMany(x=>x.quadrosocietarios.AsEnumerable(),属性QuadroSocietario);
等待任务执行;
等待任务完成;
}
返回modelArray.Length;
}
公共静态异步任务BulkInsert(SqlConnection连接、字符串tableName、IEnumerable数据、字符串[]列),其中T:class
{
使用(var-BulkCopy=new-SqlBulkCopy(连接))
使用(var reader=ObjectReader.Create(数据、列))
{
foreach(列中的字符串属性)
{
添加(新的SqlBulkCopyColumnMapping(属性,属性));
}
BulkCopy.DestinationTableName=表名;
等待BulkCopy.WriteToServerAsync(读卡器);
}
}

您是否看到某些东西不工作?Salvarempresasync做什么?如果它失败,或者使用
catch{}
隐藏错误,您将不会注意到任何错误。没有调用
Complete()
等待ExitBlock.Completionl
Salvarempresasync
引发的任何错误都将在最终的
Wait
BoundedCapacity=10000
中被收回?在10001发生了什么?在这段代码中,唯一可以抛出的是丢失的代码。也许
salvarempresasync
有错误?也许程序从不等待完成?也许应用程序内存不足是因为
SaveBlock
缓存了10000个缓冲区,每个缓冲区包含1000个项目,在内存中保留了1000万行??并尝试在同一数据库中执行32次并发批插入?这保证了数据库中的阻塞。假设您使用SqlBulkCopy,请完全删除MaxDop参数,并使用一个合理的
BoundedCapacity
数字,尽管只要
1
就可以了-如果SqlBulkCopy一直很慢,则缓冲几乎没有什么好处
public static async Task<int> SalvarEmpresaAsync(EmpresaModel[] modelArray)
{
    using (var Connection = new SqlConnection(ConnectionString))
    {
        Connection.Open();

        var TaskEmpresa = BulkInsert<EmpresaModel>(Connection, "Empresas", modelArray, PropertiesEmpresa);
        var TaskQuadroSocietario = BulkInsert<QuadroSocietarioModel>(Connection, "QuadroSocietario", modelArray.SelectMany(x => x.QuadrosSocietarios).AsEnumerable(), PropertiesQuadroSocietario);

        await TaskEmpresa;
        await TaskQuadroSocietario;
    }


    return modelArray.Length;
}


public static async Task BulkInsert<T>(SqlConnection connection, string tableName, IEnumerable<T> data, string[] columns) where T: class
{
     using (var BulkCopy = new SqlBulkCopy(connection))
     using (var reader = ObjectReader.Create(data, columns))
     {
         foreach (string property in columns)
         {
             BulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping(property, property));
         }

         BulkCopy.DestinationTableName = tableName;
         await BulkCopy.WriteToServerAsync(reader);
     }
 }