Search code examples
c#parallel.foreach

C# Parallel.Foreach that is not peforming action on all items in list


    public static void RemoveAllNetworkPrinters()
    {
        ManagementScope oManagementScope = new ManagementScope(ManagementPath.DefaultPath);
        oManagementScope.Connect();

        SelectQuery oSelectQuery = new SelectQuery();
        oSelectQuery.QueryString = @"SELECT * FROM Win32_Printer WHERE ServerName IS NOT NULL";

        using (ManagementObjectSearcher oObjectSearcher = new ManagementObjectSearcher(oManagementScope, oSelectQuery))
        {
            using (ManagementObjectCollection oObjectCollection = oObjectSearcher.Get())
            {
                if (oObjectCollection.Count != 0)
                {
                    foreach (ManagementObject oItem in oObjectCollection)
                    {
                        oItem.Delete();

                    }
                }
            }
        }
    }

    public static void RemoveAllNetworkPrintersParallel()
    {
        ManagementScope oManagementScope = new ManagementScope(ManagementPath.DefaultPath);
        oManagementScope.Connect();

        SelectQuery oSelectQuery = new SelectQuery();
        oSelectQuery.QueryString = @"SELECT * FROM Win32_Printer WHERE ServerName IS NOT NULL";

        using (ManagementObjectSearcher oObjectSearcher = new ManagementObjectSearcher(oManagementScope, oSelectQuery))
        {
            using (ManagementObjectCollection oObjectCollection = oObjectSearcher.Get())
            {
                if (oObjectCollection.Count != 0)
                {
                    Parallel.ForEach(oObjectCollection.OfType<ManagementObject>().ToList(), oItem =>
                    {
                        oItem.Delete();
                    });
                }
            }
        }
    }

I have a question in reference to the Parallel.Foreach in c#. I have been testing with and see something odd in example I am providing for testing purposes. When I perform the non parallel version of this function it works fine but when I do a parallel version anywhere between 1-2 items will not process in the list I am cycling through. I have read the msdn documentation but must be missing something here. I know you can't guarantee the order items will be processed but thought it was guaranteed all items would be processed in the list? Any help in understanding or what I am doing wrong would be greatly appreciated. Thanks


Solution

  • As discussed in comments, ManagementObject.Delete() is not thread safe operation, so you should not use it from different threads MSDN

    Any public static ( Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

    But if you really need to do this and you want to use lock there, you can do smthg like this

    var lockObject = new Object();
    
    Parallel.ForEach(/*.....*/, item =>
    {
        lock (lockObject)
        {
            // do your magic here
        }
    });
    

    BUT as I said its is not make sense to use this code since it will be slower that ordinal foreach.

    So, my recommendation - use just foreach.