async/await is about asynchrony, whereas
Parallel.ForEach is about parallelism. They’re related concepts, but not the same.
Parallel.ForEach is used when you want to execute the same operation on all the items in a collection, in parallel, blocking the current thread until all operations have completed.
async/await is used when the current operation can’t make any more progress until a particular asynchronous operation has completed, but you don’t want to block the current thread. This is particularly useful in two situations:
- Writing code which basically kicks off various asynchronous operations, one after the other, on the UI thread, accessing the UI briefly between operations. (It’s more general than that, but that’s a simple example.) You don’t want to block the UI thread, but managing all of those asynchronous operations is a pain otherwise.
- Handling lots of long-running operations at a time – e.g. in a web server. Each individual request may take a long time due to calling into other web service, databases etc – but you don’t want to have one thread per request, as threads are a relatively expensive resource.
You can combine parallelism and asynchrony by kicking off a new task which will call
Parallel.ForEach, and then awaiting that task. (Just as one example.)