How to make multiple async/await chaining in C#? For example, start few HTTP requests and then do not wait all of them, but start new request after each completed?
Asked
Active
Viewed 6,010 times
2
-
I would turn each request into a seperate thread, and then have a callback that these threads can call back into the main app to queue them. Taking care to lock before you insert into the queue, and before you pull out. – Brian S Aug 07 '14 at 12:03
-
I want to use async/await to avoid using multiple threads. – Dark Hydra Aug 07 '14 at 12:05
-
2@GREnvoy: The whole point of Tasks is to stop thinking in terms of threads. There is a Task answer to this question, and the system can do any necessary threading better than you can. – david.pfx Aug 07 '14 at 12:25
-
1@Chrome See [this answer](http://stackoverflow.com/a/22036708/1906557). max 20 tasks are downloading at any time, and as soon as one finishes a new task is started.. – I4V Aug 07 '14 at 12:44
3 Answers
13
The easiest way to do this is to write an async
method:
async Task DownloadAndFollowupAsync(...)
{
await DownloadAsync();
await FollowupAsync();
}
Which you can then use with await Task.WhenAll
:
await Task.WhenAll(DownloadAndFollowupAsync(...),
DownloadAndFollowupAsync(...));

Stephen Cleary
- 437,863
- 77
- 675
- 810
2
If you want to perform some async
action on a collection of items with a limited degree of parallelism, then probably the simplest way is to use ActionBlock
from TPL Dataflow, since it supports async
delegates (unlike most other parallel constructs in TPL, like Parallel.ForEach()
).
var block = new ActionBlock<string>(
url => DownloadAsync(url),
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = few });
foreach (var url in urls)
block.Post(url);
block.Complete();
await block.Completion;

svick
- 236,525
- 50
- 385
- 514
1
You can use the ContinueWith extension method of Tasks for this purpose or the extension that takes a Func and is used to return results.

Savvas Kleanthous
- 2,695
- 17
- 18
-
1Probably because `ContinueWith` is dangerous in `async` code; you should use `await` instead. – Stephen Cleary Aug 07 '14 at 12:35
-
@StephenCleary You can always use ConfigureAwait to avoid deadlocks. You just have to be a bit more careful. – Savvas Kleanthous Aug 07 '14 at 14:22
-
3The "dangerous" use I'm referring to is the way that `ContinueWith` defines its default task scheduler, and the fact that it doesn't naturally propagate exceptions/cancellation, nor resume in a captured context automatically. `await` should be the default choice in >99% of cases. – Stephen Cleary Aug 07 '14 at 15:43
-
@StephenCleary ran into an issue you warned about. The task resulting of continuewith was never running to completion according to it's status. Separate awaits fixed it. – Dasith Wijes Nov 18 '16 at 13:52