简体   繁体   English

如何在 C# 中高效地并行执行多个异步调用?

[英]How to execute multiple async calls in parallel efficiently in C#?

I have a list of client id and for each client id I need to get data from cassandra.我有一个client id列表,对于每个client id ,我需要从 cassandra 获取数据。 So I am executing all those client id's in parallel instead of using IN clause query which is not good for performance.因此,我正在并行执行所有这些客户端 ID,而不是使用对性能不利的 IN 子句查询。

So I came up with below code which execute multiple async calls for each client id and it does the job by getting data out of cassandra but is it the right way to execute multiple async calls in parallel or am I doing something wrong here which can affect my performance?所以我想出了下面的代码,它为每个客户端 ID 执行多个异步调用,它通过从 cassandra 中获取数据来完成这项工作,但它是并行执行多个异步调用的正确方法还是我在这里做错了可能会影响我的表现?

public async Task<IList<Item>> GetAsync(IList<int> clientIds, int processId, int proc, Kyte kt)
{
    var clientMaps = await ProcessCassQueries(clientIds, (ct, batch) => mapper.SingleOrDefaultAsync<ItemMapPoco>(itemMapStmt, batch), "GetPIMValue");

    if (clientMaps == null || clientMaps.Count <= 0)
    {
        return null;
    }
    // .. do other stuff and return
}

// this executes multiple client ids in parallel - but is it the right way considering performance?
private async Task<List<T>> ProcessCassQueries<T>(IList<int> ids, Func<CancellationToken, int, Task<T>> mapperFunc, string msg) where T : class
{
    var requestTasks = ids.Select(id => ProcessCassQuery(ct => mapperFunc(ct, id), msg));
    return (await Task.WhenAll(requestTasks)).Where(e => e != null).ToList();
}

// this might not be good
private Task<T> ProcessCassQuery<T>(Func<CancellationToken, Task<T>> requestExecuter, string msg) where T : class
{
    return requestExecuter(CancellationToken.None);
}

I recently started using C# so have limited knowledge around that so maybe my code might be not good in terms of performance.我最近开始使用C#所以对这方面的知识有限,所以我的代码在性能方面可能不好。 Specially ProcessCassQueries and ProcessCassQuery methods.特别ProcessCassQueriesProcessCassQuery方法。 Anything that can be improved here or can be written in a better way considering it's a prod code?考虑到它是产品代码,这里有什么可以改进或可以以更好的方式编写的吗?

Update:更新:

Basis on suggestion, using semaphore to limit number of async calls as shown below:根据建议,使用信号量来限制异步调用的数量,如下所示:

private var semaphore = new SemaphoreSlim(20);

private async Task<List<T>> ProcessCassQueries<T>(IList<int> ids, Func<CancellationToken, int, Task<T>> mapperFunc, string msg) where T : class
{
    var tasks = ids.Select(async id => 
    {
        await semaphore.WaitAsync();
        try
        {
            return await ProcessCassQuery(ct => mapperFunc(ct, id), msg);
        }
        finally
        {
            semaphore.Release();
        }
    });

  return (await Task.WhenAll(tasks)).Where(e => e != null).ToList();
}

What you are doing is correct.你在做什么是正确的。 You are launching a bunch of tasks all at once, and then await all of them to complete.您正在同时启动一堆任务,然后等待所有任务完成。 There is no inefficiency or bottleneck regarding this specific C# code.这个特定的 C# 代码没有效率低下或瓶颈。 It is a bit strange that you pass a hardcoded CancellationToken.None in the ProcessCassQuery , but it will not affect the performance.ProcessCassQuery中传递硬编码的CancellationToken.None有点奇怪,但它不会影响性能。 The performance of the whole operation now depends on the behavior of the Cassandra database, when it is bombarded with multiple simultaneous requests.整个操作的性能现在取决于 Cassandra 数据库在受到多个同时请求的轰炸时的行为。 If it is optimized for this kind of usage then everything will be OK.如果它针对这种用法进行了优化,那么一切都会好起来的。 If not, then your current setup doesn't offer the flexibility of configuring the level of concurrency to a value optimal for the specific database engine.如果不是,那么您当前的设置不提供将并发级别配置为特定数据库引擎的最佳值的灵活性。 For ways to limit the amount of concurrent async I/O operations look here .有关限制并发异步 I/O 操作数量的方法,请查看此处

As a side note, according to the official guidelines the asynchronous methods ProcessCassQueries and ProcessCassQuery should have the Async suffix.作为旁注,根据官方指南,异步方法ProcessCassQueriesProcessCassQuery应该具有Async后缀。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM