Start here. This is the direct spoken answer to practice first.
Why this question matters
Parallel APIs differ in expression and control, but both spend thread-pool workers and add partitioning and merge overhead. A good choice starts by proving the work is independent and CPU-bound.
I would use PLINQ for an in-memory data transformation or aggregation that is naturally expressed as a query and whose elements can be processed independently. I would use Parallel.ForEach for an imperative CPU-bound loop where I need explicit control around each iteration. I would use neither for ordinary asynchronous I/O; Task.WhenAll, bounded async concurrency, or a channel is usually a better fit there. I would also keep the sequential version when the collection or per-item work is too small to repay parallel overhead.