AsParallel () .ForAll vs async await

2

When using AsParallel().ForAll , and when to use async await ?

I'm providing an example with a download routine and a file manipulation routine.

AsParallel().ForAll performs better in parallel download operation.
async await performs best in parallel file manipulation operation.

If anyone can explain the difference and the best use scenario for each, I thank you.

Code (also available in .NET Fiddle ):

using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Parallel
{
    public enum Actions
    {
        TestParallelDownload,
        TestParallelSaveFile,
        TestAsyncDownload,
        TestAsyncSaveFile
    }

    public class Program
    {
        public static async Task Main(string[] args)
        {
            try
            {
                var stopWatch = Stopwatch.StartNew();
                var itemAmount = 5;

                await Test(Actions.TestParallelDownload, itemAmount);
                await Test(Actions.TestParallelSaveFile, itemAmount);

                await Test(Actions.TestAsyncDownload, itemAmount);
                await Test(Actions.TestAsyncSaveFile, itemAmount);

                stopWatch.Stop();
                Console.WriteLine("Finish {0}", stopWatch.Elapsed);
                Console.ReadLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Err", ex.Message);
                Console.ReadLine();
            }
        }

        public static async Task Test(Actions action, int itemAmount)
        {
            string[] items = Enumerable.Range(0, itemAmount).Select(i => Guid.NewGuid().ToString()).ToArray();
            var stopWatch = Stopwatch.StartNew();

            switch (action)
            {
                case Actions.TestParallelDownload:
                    items.AsParallel().ForAll(item => DownloadAsync(item));
                    break;
                case Actions.TestParallelSaveFile:
                    items.AsParallel().ForAll(item => SaveAsync(item));
                    break;
                case Actions.TestAsyncDownload:
                    foreach (var item in items)
                        await DownloadAsync(item);
                    break;
                case Actions.TestAsyncSaveFile:
                    foreach (var item in items)
                        await SaveAsync(item);
                    break;
            }

            stopWatch.Stop();

            Console.WriteLine($"{action.ToString()} Call: Time: {stopWatch.Elapsed}");
        }

        public static async Task SaveAsync(string textToWrite)
        {
            string filePath = @"C:\temp\file2.txt";
            byte[] encodedText = Encoding.Unicode.GetBytes(textToWrite);

            using (var sourceStream = new FileStream(filePath,
                FileMode.Append, FileAccess.Write, FileShare.None,
                bufferSize: 4096, useAsync: true))
            {
                await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
            };
        }

        public static async Task DownloadAsync(string name)
        {
            var uri = new Uri("https://images.sftcdn.net/images/t_app-logo-l,f_auto,dpr_auto/p/ce2ece60-9b32-11e6-95ab-00163ed833e7/2183169552/the-test-fun-for-friends-logo.png");
            using (var client = new WebClient())
            {
                await client.DownloadFileTaskAsync(uri, $"{name}.png");
            }
        }
    }
}

Unfortunately, because it contains file manipulation, the code does not run correctly in cloud , you need to create a .NET Core Console project to run it.

    
asked by anonymous 14.11.2018 / 17:59

1 answer

2

As commented by João Martins , AsParallel is multi-threading - that is, you are executing tasks in parallel using multiple threads - and async/await is asynchronous - that is, the task can be interrupted, releasing the current thread , and will continue later, possibly in another thread .

So in the case of your actions TestParallel* , you'll potentially be using more than thread . But note that there is a bug in them: because there is no await (or in the case of Linq / PLinq a .Result or .Wait() in methods that return Task/Task<T> ) it may happen that the program finishes and the downnload or files do not complete ...

An alternative that would solve this and give the sense of parallelism would be to change to something like:

await Task.WhenAll(items.Select(item => DownloadAsync(item));

In the case of actions TestAsync* , they will run serially in a single thread , which will stop at the start of I / O operations and continue at the end of every one.

    
18.11.2018 / 22:25