简述
Parallel:提供对并行循环和区域的支持,Parallel 主要提供了 For 系列方法和 ForEach 系列方法,并行处理所有项。两个系列的方法都有若干重载,但最常用也最易用的是这两个。
ParallelQuery:ParallelQuery
Parallel例子
- Parallel.For(int fromInclude, int toExclude, Action
body)
Parallel.For 类似for循环,区别是Parallel.For 是异步处理多条数据,意味着它是无序输出。
Parallel.For(0, 6, (i) => {
Console.Write($"{i} ");
});
Console.WriteLine();
//输出 可能为:0 4 1 3 5 2
- Parallel.ForEach
(IEnumerable , Action )
那么Parallel.ForEach就是异步的foreach,仿照上面离职改造一下
var all = new [] { 0, 1, 2, 3, 4, 5, 6};
Parallel.ForEach(all, (i) => {
Console.Write($"{i} ");
});
Console.WriteLine();
//输出 可能为:0 4 5 3 1 2
Parallel优缺点
Parallel有啥优点?
从语法来说,Parallel.For 和 Parallel.ForEach比原生的for 和 foreach难用,那么有啥有点呢?Parallel主要还是用到异步,大批量数据处理速度上占有优势,但是不考虑顺序的前提下。
Parallel有啥缺点?
“并行”异步会涉及到线程安全问题。还好有解决方案,可以用Interlocked,Interlocked提供了一些简单计算原子操作,可以去查询一下相关资料。
使用案例
public static int CalcFactorial(int n)
{
return n <= 2 ? n:n * CalcFactorial(n - 1);
}
public static int SumFactorial()
{
int[] datas = { 4, 5, 7, 9 };
int sum = 0;
Parallel.ForEach(datas, n => {
Interlocked.Add(ref sum, CalcFactorial(n));
});
return sum;
}
ParallelQuery 使用案例
跟上面一样,计算阶乘
public static int CalcFactorial(int n)
{
return n <= 2 ? n:n * CalcFactorial(n - 1);
}
public static int SumFactorials()
{
int[] datas = { 4, 5, 7, 9 };
return datas.AsParallel().Select(s => CalcFactorial(s)).Sum();
}
还可以这样用
ConcurrentQueue<Product> products = new ConcurrentQueue<Product>();
/*向集合中添加多条数据*/
Parallel.For(0, 600, (num) =>
{
products.Enqueue(new Product() { Category = "Category" + num, Name = "Name" + num, SellPrice = num });
});
CancellationTokenSource cts = new CancellationTokenSource();
/*创建tk1 任务 查询 符合 条件的数据*/
Task<ParallelQuery<Product>> tk1 = new Task<ParallelQuery<Product>>((ct) =>
{
Console.WriteLine("开始执行 tk1 任务", products.Count);
Console.WriteLine("tk1 start任务中 数据结果集数量为:{0}", products.Count);
var result = products.AsParallel().Where(p => p.Name.Contains("1") && p.Name.Contains("2"));
Console.WriteLine("tk1 end任务中 数据结果集数量为:{0}", result.Count());
return result;
}, cts.Token);
tk1.Start();
Task.WaitAll(tk1);
Console.WriteLine("tk1任务结果输出,筛选后记录总数为:{0}", tk1.Result.Count());
tk1.Dispose();
cts.Dispose();
Console.ReadLine();
//Product类
class Product
{
public string Name { get; set; }
public string Category { get; set; }
public int SellPrice { get; set; }
}
具体用法请查看相关资料。