C# 线程池和数据库连接池与Task.WaitAll vs Task.WhenAll-在高负载下

C# 线程池和数据库连接池与Task.WaitAll vs Task.WhenAll-在高负载下,c#,asp.net-core,async-await,connection-pooling,C#,Asp.net Core,Async Await,Connection Pooling,我有两种方法可以从数据库中获取数据 var data1 = await GetData1(); var data2 = await GetData2(); 为了同时拨打这两个电话,我这样做: var data1Task = GetData1(); var data2Task = GetData2(); Task.WaitAll(data1Task, data2Task); public async Task<List<DbModel>> GetData1(long c

我有两种方法可以从数据库中获取数据

var data1 = await GetData1();
var data2 = await GetData2();
为了同时拨打这两个电话,我这样做:

var data1Task = GetData1();
var data2Task = GetData2();
Task.WaitAll(data1Task, data2Task);
public async Task<List<DbModel>> GetData1(long customerId)
{
    string sql = $@"
    SELECT          
        id as Id, 
        title as Title
        ... more cols here
                
    FROM 
        table_1
    LEFT JOIN 
        table_2
    ON 
        id = another_id
    WHERE 
        id = @CustomerIdDbParam 
    ";

    List<DbModel> dbResponse = null;

    using (IDbConnection connection = new NpgsqlConnection(_connectionString.Value))
    {
        dbResponse = (await connection.QueryAsync<DbModel>(sql,
        new
        {
            CustomerIdDbParam = customerId
        })).ToList();
    }

    return dbResponse;
}
。。。但是,这耗尽了我的连接池(在高负载下,大约每分钟4k请求)

当我重构到
任务时,当所有
都正常工作时:

var data1Task = GetData1();
var data2Task = GetData2();
await Task.WhenAll(data1Task, data2Task);
我想问一下WaitAll(阻塞线程)与连接池耗尽有什么关系? 我知道WaitAll会阻止线程池中的线程,但它和连接池有什么关系呢

编辑: GetData1&2方法如下所示:

var data1Task = GetData1();
var data2Task = GetData2();
Task.WaitAll(data1Task, data2Task);
public async Task<List<DbModel>> GetData1(long customerId)
{
    string sql = $@"
    SELECT          
        id as Id, 
        title as Title
        ... more cols here
                
    FROM 
        table_1
    LEFT JOIN 
        table_2
    ON 
        id = another_id
    WHERE 
        id = @CustomerIdDbParam 
    ";

    List<DbModel> dbResponse = null;

    using (IDbConnection connection = new NpgsqlConnection(_connectionString.Value))
    {
        dbResponse = (await connection.QueryAsync<DbModel>(sql,
        new
        {
            CustomerIdDbParam = customerId
        })).ToList();
    }

    return dbResponse;
}
公共异步任务GetData1(长customerId)
{
字符串sql=$@”
挑选
id作为id,
标题作为标题
…这里有更多的可乐
从…起
表1
左连接
表2
在…上
id=另一个id
哪里
id=@CustomerIDBParam
";
List dbResponse=null;
正在使用(IDbConnection connection=newNPGSQLConnection(_connectionString.Value))
{
dbResponse=(wait connection.QueryAsync(sql,
新的
{
customerIDBParam=customerId
})).ToList();
}
返回dbResponse;
}
我得到的例外是:

  • 超时:
  • System.TimeoutException:操作已超时。在Npgsql.NpgsqlConnector.Authenticate上
    和
    
    System.TimeoutException:操作已超时。在Npgsql.NpgsqlConnector.Open(NpgsqlTimeout超时

  • 游泳池耗尽:

  • System.aggregateeexception:发生一个或多个错误。(操作已超时。)(连接池已耗尽,请提升MaxPoolSize(当前为200)或超时(当前为15秒))

    如何知道连接池已耗尽(使用
    Task.WaitAll
    方法)?是否有一些全局属性返回池中的可用连接?抛出异常,表示该连接已耗尽,并且我的DB connections count chart从100激增到700您正在循环中调用它?我的意思是,两个查询如何耗尽200个连接池?是的,但该处置安排在
    等待
    和ne之后eds一个要运行的线程。使用
    wait whalll
    ,您释放启动线程,而使用
    WaitAll
    它保持阻塞状态,从而增加
    线程池的压力,以便在数据库查询完成后运行
    Dispose
    。在您的情况下,请求在线程池线程上运行,并通过ask.WaitAll,导致前面提到的线程池不足,因此,正如上面正确提到的,线程池无法赶上并提供新线程(因为它在设计上提供新线程的速度非常慢)在等待处理连接之后运行continuations。长话短说-永远不要阻塞线程池线程,尤其是在没有非常严肃的理由这样做的情况下