-5

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

Killer X
  • 17
  • 2

3 Answers3

1

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);
    }
}
Kevin Gosse
  • 38,392
  • 3
  • 78
  • 94
0

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

Nandan
  • 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
  • 1
    It'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
0

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.

Community
  • 1
  • 1
Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810