Search code examples
c#multithreadinglinqtask-parallel-librarygeneric-collections

List<T>.RemoveAll as parallel


I would like to known an alternative to do a toProcess.RemoveAll, but in parallel. Today my code like my exemplo is working well, but in sequencial, and I'd like to be in paralle.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ParallelTest
{
    using System.Threading;
    using System.Threading.Tasks;
    class Program
    {
        static void Main(string[] args)
        {
            List<VerifySomethingFromInternet> foo = new List<VerifySomethingFromInternet>();
            foo.Add(new VerifySomethingFromInternet(@"id1", true));
            foo.Add(new VerifySomethingFromInternet(@"id2", false));
            foo.Add(new VerifySomethingFromInternet(@"id3", true));
            foo.Add(new VerifySomethingFromInternet(@"id4", false));
            foo.Add(new VerifySomethingFromInternet(@"id5", true));
            foo.Add(new VerifySomethingFromInternet(@"id6", false));

            DoSomethingFromIntert bar = new DoSomethingFromIntert();

            bar.DoesWork(foo);
            Console.ReadLine();
        }
    }

    public class DoSomethingFromIntert
    {
        bool RemoveIFTrueFromInternet(VerifySomethingFromInternet vsfi)
        {
            Console.WriteLine(String.Format("Identification : {0} - Thread : {1}", vsfi.Identification, Thread.CurrentThread.ManagedThreadId));
            // Do some blocking work at internet
            return vsfi.IsRemovable;
        }

        public void DoesWork(List<VerifySomethingFromInternet> toProcess)
        {
            Console.WriteLine(String.Format("total : {0}", toProcess.Count));
            //Remove all true return
            toProcess.RemoveAll(f => this.RemoveIFTrueFromInternet(f));
            Console.WriteLine(String.Format("total : {0}", toProcess.Count));
        }
    }
    public class VerifySomethingFromInternet
    {
        public VerifySomethingFromInternet(string id, bool remove)
        {
            this.Identification = id;
            this.IsRemovable = remove;
        }
        public string Identification { get; set; }
        public bool IsRemovable { get; set; }
    }
}

Solution

  • var newList = toProcess.AsParallel ()
                   .Where (f => !this.RemoveIFTrueFromInternet(f))
                   .ToList ();
    
    toProcess = newList;
    

    Probably this answers your question, but I'm not sure that it's really faster. Try and measure.

    Note that this may change the order of the elements in the list. If you care about order, add AsOrdered after AsParallel. (Thanks to weston for the [implicit] hint).