Advent LINQ 2013 : おまけ (Parallel.ForEach)

Advent LINQ (10): .NET 2.0でLINQを使うの回で、比較的簡単にParallel.ForEachを自前で実装出来ると書いたので、例を見せる。
 
 

namespace System.Threading.Tasks
{
    public static class Parallel
    {
        public static void ForEach<T>(IEnumerable<T> enumerable, Action<T> action)
        {
            Debug.Assert(enumerable != null);
            Debug.Assert(action != null);

            var exceptionList = new List<Exception>();
            using (var wait = new ManualResetEvent(false))
            {
                var count = 1;
                foreach (var item in enumerable)
                {
                    Interlocked.Increment(ref count);

                    ThreadPool.QueueUserWorkItem(new WaitCallback(p =>
                    {
                        try
                        {
                            try
                            {
                                action(item);
                            }
                            catch (Exception ex)
                            {
                                lock (exceptionList)
                                {
                                    exceptionList.Add(ex);
                                }
                            }
                        }
                        finally
                        {
                            if (Interlocked.Decrement(ref count) == 0)
                            {
                                wait.Set();
                            }
                        }
                    }));
                }

                if (Interlocked.Decrement(ref count) == 0)
                {
                    wait.Set();
                }

                wait.WaitOne();
            }

            if (exceptionList.Count >= 1)
            {
                throw new AggregateException(exceptionList);
            }
        }

        public static void Invoke(params Action[] actions)
        {
            ForEach(actions, action => action());
        }
    }
}

コンパイルを通すには、他にもActionクラスが必要だ。このサンプルはVSCoverageToEmmaで実装したもので、以下の場所に完全なコードがある。

VSCoverageToEmma/VSCoverageToEmma.Core/Tasks/Parallel.cs

投稿者:

kekyo

A strawberry red slime mold. Likes metaprogramming. MA. Bicycle rider. http://amzn.to/1SeuUwD