TPL を使用してフィルター タスクを実行しようとしています。ここでは、条件に基づいて数値をフィルタリングするコードを単純化しています。これがコードです。
public static void Main (string[] args)
{
IEnumerable<int> allData = getIntData ();
Console.WriteLine ("Complete Data display");
foreach (var item in allData) {
Console.Write(item);
Console.Write(" | ");
}
Console.WriteLine ();
filterAllDatas (ref allData, getConditions ());
foreach (var item in allData) {
Console.Write(item);
Console.Write(" | ");
}
Console.WriteLine ();
}
static void filterAllDatas(ref IEnumerable<int> data, IEnumerable<Func<int,bool>> conditions)
{
List<int> filteredData = data.ToList ();
List<Task> tasks = new List<Task>();
foreach (var item in data.AsParallel()) {
foreach (var condition in conditions.AsParallel()) {
tasks.Add(Task.Factory.StartNew(() => {
if (condition(item)) {
filteredData.Remove(item);
}
}));
}
}
Task.WaitAll(tasks.ToArray());
data = filteredData.AsEnumerable ();
}
static IEnumerable<Func<int,bool>> getConditions()
{
yield return (a) => { Console.WriteLine("modulo by 2"); return a % 2 == 0;};
yield return (a) => { Console.WriteLine("modulo by 3"); Thread.Sleep(3000); return a % 3 == 0;};
}
static IEnumerable<int> getIntData ()
{
for (int i = 0; i < 10; i++) {
yield return i;
}
}
ここでは、整数を 2 または 3 で割ったものを除外する単純なコードです。さて、そのスレッドスリープコードを削除すると完全に機能しますが、それを入れるとそうではありません。
通常は Thread.Sleep がないことを意味し、両方の条件が 10 回実行されます。たとえば、数値ごとに実行されます。しかし、Thread.Sleep を追加すると、最初の条件が 7 回実行され、2 番目の条件が 13 回実行されます。そして、この数が少ないため、条件をスキップします。デバッグしようとしましたが、コードの問題を指摘できるものは何も得られませんでした。
これを達成する良い方法はありますか?データのフィルター条件と同様に、パフォーマンスを向上させるために非同期および並列に機能できますか?
コードはデモのみを目的としています。
参考までに: 現在、私は Windows マシンの Xamarine スタジオで Mono を使用しています。
さらに詳細が必要な場合はお知らせください。