2

In my program I'm starting parallel tasks one by one (http requests), doing it far ahead of any actual results those tasks can return.

It looks like

while (continueTaskSwarming == true)
{
    Task.Run(() => Task());
}

Of course that way I have way more tasks scheduled than can be processed, so when I cancel them through cancellation token, it takes a lot of time to just cancel them all - they are scheduled after all, so they must actually run before they can be cancelled.

How can I organize task creation so that there always be only limited bunch of tasks ready to run, with new tasks scheduled only when there is some "place" for them? I mean, some "straight" way, something like

while (continueTaskSwarming == true)
{
    PauseUntilScheduledTaskCountIsLowerThan(100);
    Task.Run(() => Task());
}

Is that possible?

EDIT:

The obvious way, I think, is to put all tasks created into some list, removing them on completion and checking count of active/scheduled tasks. But I don't know (and don't know keywords to google it) if I can "remove" task from itself, or from ContinueWith() method. Anyone knows?

yaapelsinko
  • 639
  • 1
  • 10
  • 18
  • Unless you have a very specific limitation in mind that you want to control yourself, I'd assume that the thread pool would automatically perform some kind of throttling. – stakx - no longer contributing Oct 24 '14 at 06:27
  • To stakx: It does, of course, but as far as I can see it applies only to actually running tasks, but it can't prevent me from scheduling trillion of tasks. And I actually want to schedule virtually "unlimited" task count, stopping only on condition to stop. But there is no point to have 1000 scheduled tasks, so I want to limit it. – yaapelsinko Oct 24 '14 at 06:32

2 Answers2

2

There are lots of ways to do this. You can protect a counter (of current tasks) with a lock, using Monitor.Wait() to have the task-producing thread wait until the counter is decremented and it's safe to start another task.

Another approach is to use the Semaphore synchronization object. This does basically the same thing, but encapsulated in an easy-to-use object. You create a new Semaphore, specifying how many concurrent threads you want to be able to hold the lock at once. By having each task take a lock on the semaphore, then you can have the task-producer also lock on the semaphore and when you read the max number of tasks, the producer won't be able to continue and create another task until one of the currently running tasks completes.

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
0

If I understand correctly, you are trying to achieve limited concurrency while executing tasks

this will help you

http://msdn.microsoft.com/en-us/library/ee789351(v=vs.110).aspx

Limited concurrency level task scheduler (with task priority) handling wrapped tasks

Community
  • 1
  • 1
Sangram Chavan
  • 331
  • 1
  • 9
  • Link only answers are discouraged, the best way to tell if your answer could be considered a "link only answer" is temporarily delete all of the links in your question and ask yourself "Is this question still useful?" Links in answers should be written with the assumption that all links within them will go dead and the answer needs to contain at least enough information that another person could find the detailed information on their own with the summary information provided in the answer. – Scott Chamberlain Jan 11 '15 at 06:30