Parallelly resizing mutiple photos This code snippet is supposed to utilize async await to resize a photo file into multiple sizes in parallel. I just want to know if I am doing it in the right way. I would love to hear some ideas on how to report resize progress on file like how many of them completed.

public class PhotoProcessor : IPhotoProcessor
{
    public void Resize(string filePath, string dropLocation, List&lt;Size&gt; sizes)
    {
        Parallel.ForEach(sizes, async (size) =&gt;
        {
            var fileName = Path.GetFileName(filePath);
            var result = await Resize(filePath, dropLocation, size);
            Console.WriteLine($"Done {result} Resizing {fileName} to {size}");
        });
    }

    public async Task&lt;bool&gt; Resize(string filePath, string dropLocation, Size size)
    {
        if (!File.Exists(filePath))
        {
            throw new FileNotFoundException($"File {filePath} not found");
        }

        using (var image = new MagickImage(filePath))
        {
            var fileName = Path.GetFileNameWithoutExtension(filePath);
            var extension = Path.GetExtension(filePath);
            var newFileName = $"{fileName}_{size}{extension}";
            var newFilePath = $"{dropLocation}{newFileName}";

            var magickSize = new MagickGeometry(size.W, size.H);
            magickSize.IgnoreAspectRatio = false;
            await Task.Run(() =&gt;
            {
                image.Resize(magickSize);
                image.Write(newFilePath);
            });
        }
        return true;
    }
}
public void Resize(string filePath, string dropLocation, List&lt;Size&gt; sizes)



Why List&lt;&gt;? Following the principle of coding to the interface rather than the implementation, this should probably be IList&lt;&gt; or even IReadOnlyList&lt;&gt;.




        Parallel.ForEach(sizes, async (size) =&gt;
        {
            var fileName = Path.GetFileName(filePath);
            var result = await Resize(filePath, dropLocation, size);
            Console.WriteLine($"Done {result} Resizing {fileName} to {size}");
        });



Why async/await inside Parallel.ForEach? If each size is handled on a different thread, there's nothing to be gained by using await.




            var newFilePath = $"{dropLocation}{newFileName}";



Path.Combine exists for a reason: using that rather than manual concatenation will give more robust code.




            await Task.Run(() =&gt;
            {
                image.Resize(magickSize);
                image.Write(newFilePath);
            });



Pretend for a moment that we're not using Parallel.ForEach. The benefit of async/await with something like image processing is that you can keep the CPU busy even when one of the coroutines is blocked on I/O. But half of the I/O has already happened (maybe more if you're always scaling down rather than up). If you want to make an async version, the image load should be async.