Parallel iteration in C#?

前端 未结 6 1703
耶瑟儿~
耶瑟儿~ 2021-02-06 08:05

Is there a way to do foreach style iteration over parallel enumerables in C#? For subscriptable lists, I know one could use a regular for loop iterati

6条回答
  •  别那么骄傲
    2021-02-06 08:30

    I wrote an implementation of EachParallel() from the .NET4 Parallel library. It is compatible with .NET 3.5: Parallel ForEach Loop in C# 3.5 Usage:

    string[] names = { "cartman", "stan", "kenny", "kyle" };
    names.EachParallel(name =>
    {
        try
        {
            Console.WriteLine(name);
        }
        catch { /* handle exception */ }
    });
    

    Implementation:

    /// 
    /// Enumerates through each item in a list in parallel
    /// 
    public static void EachParallel(this IEnumerable list, Action action)
    {
        // enumerate the list so it can't change during execution
        list = list.ToArray();
        var count = list.Count();
    
        if (count == 0)
        {
            return;
        }
        else if (count == 1)
        {
            // if there's only one element, just execute it
            action(list.First());
        }
        else
        {
            // Launch each method in it's own thread
            const int MaxHandles = 64;
            for (var offset = 0; offset < list.Count() / MaxHandles; offset++)
            {
                // break up the list into 64-item chunks because of a limitiation             // in WaitHandle
                var chunk = list.Skip(offset * MaxHandles).Take(MaxHandles);
    
                // Initialize the reset events to keep track of completed threads
                var resetEvents = new ManualResetEvent[chunk.Count()];
    
                // spawn a thread for each item in the chunk
                int i = 0;
                foreach (var item in chunk)
                {
                    resetEvents[i] = new ManualResetEvent(false);
                    ThreadPool.QueueUserWorkItem(new WaitCallback((object data) =>
                    {
                        int methodIndex = (int)((object[])data)[0];
    
                        // Execute the method and pass in the enumerated item
                        action((T)((object[])data)[1]);
    
                        // Tell the calling thread that we're done
                        resetEvents[methodIndex].Set();
                    }), new object[] { i, item });
                    i++;
                }
    
                // Wait for all threads to execute
                WaitHandle.WaitAll(resetEvents);
            }
        }
    }
    

提交回复
热议问题