Passing async method into Parallel.ForEach

后端 未结 3 1292
无人及你
无人及你 2020-12-19 23:39

I was reading this post about Parallel.ForEach where it was stated that \"Parallel.ForEach is not compatible with passing in a async method.\"

So, to ch

3条回答
  •  情歌与酒
    2020-12-19 23:58

    This code works only because DoAsyncJob isn't really an asynchronous method. async doesn't make a method work asynchronously. Awaiting a completed task like that returned by Task.FromResult is synchronous too. async Task Main doesn't contain any asynchronous code, which results in a compiler warning.

    An example that demonstrates how Parallel.ForEach doesn't work with asynchronous methods should call a real asynchronous method:

        static async Task Main(string[] args)
        {
            var results = new ConcurrentDictionary();
    
            Parallel.ForEach(Enumerable.Range(0, 100), async index =>
            {
                var res = await DoAsyncJob(index);
                results.TryAdd(index.ToString(), res);
            });  
            Console.WriteLine($"Items in dictionary {results.Count}");
        }
    
        static async Task DoAsyncJob(int i)
        {
            await Task.Delay(100);
            return i * 10;
        }
    

    The result will be

    Items in dictionary 0
    

    Parallel.ForEach has no overload accepting a Func, it accepts only Action delegates. This means it can't await any asynchronous operations.

    async index is accepted because it's implicitly an async void delegate. As far as Parallel.ForEach is concerned, it's just an Action.

    The result is that Parallel.ForEach fires off 100 tasks and never waits for them to complete. That's why the dictionary is still empty when the application terminates.

提交回复
热议问题