/// <summary> /// Executes the <see cref="Func{T}"/> provided n times, awaiting for the task to be completed, limiting the /// concurrency. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="action"></param> /// <param name="times"></param> /// <param name="limit"></param> /// <returns>A Task that can be awaited.</returns> public static Task TimesLimit <T>(Func <Task <T> > action, int times, int limit) { var tcs = new TaskCompletionSource <bool>(); var counter = new SendReceiveCounter(); for (var i = 0; i < limit; i++) { SendNew(action, tcs, counter, times); } return(tcs.Task); }
private static void SendNew <T>(Func <Task <T> > action, TaskCompletionSource <bool> tcs, SendReceiveCounter counter, int maxLength) { var sendCount = counter.IncrementSent(); if (sendCount > maxLength) { return; } var t1 = action(); t1.ContinueWith(t => { if (t.Exception != null) { // ReSharper disable once AssignNullToNotNullAttribute tcs.TrySetException(t.Exception.InnerException); return; } var received = counter.IncrementReceived(); if (received == maxLength) { tcs.TrySetResult(true); return; } SendNew(action, tcs, counter, maxLength); }, TaskContinuationOptions.ExecuteSynchronously); }
private static void SendNew <T>(Func <Task <T> > action, TaskCompletionSource <bool> tcs, SendReceiveCounter counter, int maxLength) { var sendCount = counter.IncrementSent(); if (sendCount > maxLength) { return; } Task.Run(async() => { try { await action().ConfigureAwait(false); } catch (Exception ex) { tcs.TrySetException(ex); return; } var received = counter.IncrementReceived(); if (received == maxLength) { tcs.TrySetResult(true); return; } SendNew(action, tcs, counter, maxLength); }).Forget(); }