How to throttle multiple asynchronous tasks?

前端 未结 6 1386
野趣味
野趣味 2020-12-03 12:36

I have some code of the following form:

static async Task DoSomething(int n) 
{
  ...
}

static void RunThreads(int totalThreads, int throttle) 
{
  var task         


        
6条回答
  •  囚心锁ツ
    2020-12-03 13:19

    Here are some extension method variations to build on Sriram Sakthivel answer.

    In the usage example, calls to DoSomething are being wrapped in an explicitly cast closure to allow passing arguments.

    public static async Task RunMyThrottledTasks()
    {
        var myArgsSource = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        await myArgsSource
            .Select(a => (Func>)(() => DoSomething(a)))
            .Throttle(2);
    }
    
    public static async Task DoSomething(int arg)
    {
        // Await some async calls that need arg..
        // ..then return result async Task..
        return new object();
    }
    
    public static async Task> Throttle(IEnumerable>> toRun, int throttleTo)
    {
        var running = new List>(throttleTo);
        var completed = new List>(toRun.Count());
        foreach(var taskToRun in toRun)
        {
            running.Add(taskToRun());
            if(running.Count == throttleTo)
            {
                var comTask = await Task.WhenAny(running);
                running.Remove(comTask);
                completed.Add(comTask);
            }
        }
        return completed.Select(t => t.Result);
    }
    
    public static async Task Throttle(this IEnumerable> toRun, int throttleTo)
    {
        var running = new List(throttleTo);
        foreach(var taskToRun in toRun)
        {
            running.Add(taskToRun());
            if(running.Count == throttleTo)
            {
                var comTask = await Task.WhenAny(running);
                running.Remove(comTask);
            }
        }
    }
    
        

    提交回复
    热议问题