For examples, I have 10 tasks. I want to run x tasks in the same time, if any task finish, other tasks will be added to run. It likes queues in Internet Download Manager
-
Is it an important order of executing tasks? Can you wait until all executed? Are you returning something from task? – kat1330 Mar 15 '17 at 01:43
-
2Any research to show? [ask] – Mar 15 '17 at 01:49
-
3Use TPL Dataflow. Does exactly what you need. – Cory Nelson Mar 15 '17 at 01:50
-
@kat1330 Ignore order. It likes queues in Internet Download Manager – Killer X Mar 15 '17 at 02:31
-
@killerX Then you can use `Task.WhenAll()`. I added below. – kat1330 Mar 15 '17 at 02:58
3 Answers
As Cory Nelson pointed out, the Microsoft.Tpl.Dataflow does what you need. Start by adding the nuget package, then instantiate an ActionBlock
with the settings you want:
var actionBlock = new ActionBlock<string>(new Action<string>(Execute), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 10 });
Here, it will call the Execute
method for every string you enqueue (the payload could be something else, here I'm assuming the string is the url of the file you wish to download). That ActionBlock
will ensure that no more than 10 threads are running concurrently.
Use the Post
method to enqueue some work:
actionBlock.Post("http://.../");
Here is a simple proof of concept:
class Program
{
private static int ConcurrentActions = 0;
public static void Main()
{
var actionBlock = new ActionBlock<string>(new Action<string>(Execute), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 10 });
for (int i = 0; i < 20; i++)
{
actionBlock.Post(i.ToString());
}
actionBlock.Complete();
while (!actionBlock.Completion.IsCompleted)
{
Console.WriteLine("Concurrent actions: {0}", ConcurrentActions);
Thread.Sleep(200);
}
Console.WriteLine("Done");
Console.ReadLine();
}
private static void Execute(string url)
{
Interlocked.Increment(ref ConcurrentActions);
Thread.Sleep(1000); // Workload
Interlocked.Decrement(ref ConcurrentActions);
}
}

- 38,392
- 3
- 78
- 94
Do you want to chain the tasks ? As in once 1st task finishes the 2nd one starts ?
You can use ContinueWith()
Refer msdn: https://msdn.microsoft.com/en-us/library/dd537612(v=vs.110).aspx

- 41
- 1
- 7
-
Use: Parallel.Invoke - MSDN Reference: https://msdn.microsoft.com/en-us/library/dd537609(v=vs.110).aspx – Nandan Mar 15 '17 at 01:47
-
Just [Edit](http://stackoverflow.com/posts/42799714/edit) your answer, don't post revisions as a comment – Mar 15 '17 at 01:52
-
1It's slightly more complex than that. OP wants that at any point in time, there is x tasks running concurrently. Using `ContinueWith`,you'd have to predict the order the tasks will finish – Kevin Gosse Mar 15 '17 at 07:18
For examples, I have 10 tasks. I want to run x tasks in the same time
This is a concurrency throttling scenario.
If by "task", you mean some CPU-bound code that you want to run (that is, each "task" is synchronous in nature), then the appropriate tool would be to set DegreeOfParallelism
on a Parallel
or PLINQ call, something like:
data.AsParallel().WithDegreeOfParallelism(x).Select(d => ...).ToList();
If by "task", you mean an actual Task
(that is, each "task" is asynchronous in nature), then the appropriate tool would be to use a SemaphoreSlim
with Task.WhenAll
, something like:
var throttler = new SemaphoreSlim(x);
var tasks = data.Select(async d =>
{
await throttler.WaitAsync();
try { ... }
finally { throttler.Release(); }
}).ToList();
await Task.WhenAll(tasks);
Alternatively, you could use TPL Dataflow, which will work with either synchronous or asynchronous "task"s.

- 1
- 1

- 437,863
- 77
- 675
- 810