C# 多线程系列(四)
Parallel类
Parallel类定义了for、foreach和invoke的静态方法。Parallel类使用多个任务,因此使用多个线程来完成这个作业。
Parallel.For
Parallel.For()方法类似于C#的for循环语句,也是多次执行一个任务。使用Parallel.For方法,可以并行运行迭代。迭代的顺序没有定义。
Parallel.For(0, 10, i => { Console.WriteLine("idx:{0}, task:{1}, thread:{2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId); });//从结果可以看出,顺序是不能保证的。
也可以提前中断for方法。for()方法的一个重载版本接受第三个Action<int, ParallelLoopState>类型的参数。使用这些参数定义一个方法,就可以调用ParallelLoopState的Break()或Stop()方法,以影响循环的结果。
- break() ,循环应在系统方便的时候尽早停止执行当前迭代之外的迭代。
- stop(),循环应在系统方便的时候尽早停止执行。
ParallelLoopResult result = Parallel.For(0, 10, (int i, ParallelLoopState pls) => { Console.WriteLine("idx:{0}, task:{1}, thread:{2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId); Thread.Sleep(10); if (i > 5) pls.Break();//尽早停止,并没有实现立即停止 }); Console.WriteLine("result.IsCompleted {0}", result.IsCompleted); Console.WriteLine("result.LowestBreakIteration {0}", result.LowestBreakIteration);
Parallel.For方法可能使用几个线程来执行循环,如果需要对每个线程进行初始化,就可以使用Parallel.For<TLocal>()方法。出了from和to对应的值外,还接受三个委托参数。
- 第一个参数类型是Func<TLocal>,该方法每个线程只调用一次。
- 第二个参数为循环体定义了委托,该委托的第一个参数是循环迭代,第二个参数ParallelLoopState允许停止迭代(如上例),第三个参数是从init方法返回的值。
- 第三个参数指定一个委托Action<TLocal>,该方法每个线程只调用一次。
Parallel.For<string>(0, 10, () => { Console.WriteLine("---init thread {0}, task{1}", Thread.CurrentThread.ManagedThreadId, Task.CurrentId); return string.Format("t{0}", Thread.CurrentThread.ManagedThreadId); }, (i, pls, str1) => { Console.WriteLine("!!!body i {0} str1 {1} thread {2} task {3}", i, str1, Thread.CurrentThread.ManagedThreadId, Task.CurrentId); Thread.Sleep(10); return string.Format("i {0}", i); }, (str1) => { Console.WriteLine("@@@finally {0}", str1); });
Parallel.ForEach
Parallel.ForEach方法遍历实现了IEnumerable的集合,其方式类似于foreach语句,但以异步方式遍历。这里也没有确定遍历顺序。
string[] arr = { "name", "kkk", "iii", "yyy", "zzz", "111" }; Parallel.ForEach<string>(arr, value => Console.WriteLine(value)); Parallel.ForEach<string>(arr, (value, pls, k) => { Console.WriteLine("{0}, {1}", value, k); if (value == "kkk") pls.Stop(); });
Parallel.Invoke
如果多个任务应并行运行,就可以使用Parallel.Invoke方法。
public static void Invoke(params Action[] actions); public static void Invoke(ParallelOptions parallelOptions, params Action[] actions);