Task.StartNew Parallel.ForEach not waiting

I have this code:

await Task.Factory.StartNew(
    () => Parallel.ForEach(
        urls,
        new ParallelOptions { MaxDegreeOfParallelism = 2 },
        async url =>
        {
           Uri uri = new Uri(url);
           string filename = System.IO.Path.GetFileName(uri.LocalPath);

           using (HttpClient client = new HttpClient())
           using (HttpResponseMessage response = await client.GetAsync(url))
           using (HttpContent content = response.Content)
           {
               // ... Read the string.
               using (var fileStream = new FileStream(config.M_F_P + filename, FileMode.Create, FileAccess.Write))
               {
                   await content.CopyToAsync(fileStream);
               }
           }
        }));

MessageBox.Show("Completed");

It is supposed to process a list of more than 800 elements, but it does not wait for the download and file to complete. In fact, it starts to download and write, shows a message, and then continues to download in the background ... I need to upload many files in parallel and asynchronous mode, but I have to wait until all of them are loaded. What is wrong with this code?

+4
source share
1 answer

Parallel.ForEachdoes not work with async. He expects Action, but to wait for the asynchronous method he needs to receive Func<Task>.

TPL Dataflow ActionBlock, async. ( ) . parallelism (, , ). :

var block = new ActionBlock<string>(async url => 
{
    Uri uri = new Uri(url);
    string filename = System.IO.Path.GetFileName(uri.LocalPath);

    using (HttpClient client = new HttpClient())
    using (HttpResponseMessage response = await client.GetAsync(url))
    using (HttpContent content = response.Content)
    {
       // ... Read the string.
       using (var fileStream = new FileStream(config.M_F_P + filename, FileMode.Create, FileAccess.Write))
       {
           await content.CopyToAsync(fileStream);
       }
    }
}, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 2 } );

foreach (var url in urls)
{
    block.Post(url);
}

block.Complete();
await block.Completion;
// done
+4

Source: https://habr.com/ru/post/1624691/


All Articles