RSS

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

25 12月
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

広告
 
コメントする

投稿者: : 2013/12/25 投稿先 .NET, LINQ

 

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中

 
%d人のブロガーが「いいね」をつけました。