线程、任务和同步学习笔记(四)
1、抽象线程类Parallel的For和ForEach方法可以多次调用同一个方法。Parallel类的Invoke方法允许同时调用不同的方法。
1 using System; 2 using System.Threading; 3 using System.Threading.Tasks; 4 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 ParallelLoopResult result = Parallel.For(0, 10, i => 10 { 11 Console.WriteLine("{0}, task: {1}, thread: {2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId); 12 Thread.Sleep(10); 13 }); 14 Console.WriteLine(result); 15 Console.WriteLine(result.IsCompleted); 16 } 17 }
运行结果:
2、For方法的循环可以中断,中断的方式是使用ParallelLoopState的Break方法。
1 using System; 2 using System.Threading; 3 using System.Threading.Tasks; 4 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 ParallelLoopResult result = Parallel.For(0, 30, (int i, ParallelLoopState state) => 10 { 11 Console.WriteLine("{0}, task: {1}, thread: {2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId); 12 Thread.Sleep(10); 13 if (i > 10) 14 { 15 state.Break(); 16 } 17 }); 18 Console.WriteLine(result.IsCompleted); 19 Console.WriteLine("Lowest break iteration: {0}.", result.LowestBreakIteration); 20 } 21 }
运行结果:
从上图所示的运行结果可以看出,程序并不能保证循环变量 i 的值都满足条件。
3、For方法的泛型版本还接受3个委托参数。第一个参数的类型是Func<TLocal>,该方法在每个线程中调用一次;第二个参数为循环体定义了委托;第三个参数的类型为Action<TLocal>,该方法是一个线程退出方法,它同样也是在每个线程中调用一次。
1 using System; 2 using System.Threading; 3 using System.Threading.Tasks; 4 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 Parallel.For<string>(0, 20, 10 () => 11 { 12 Console.WriteLine("Init thread {0}, task {1}", Thread.CurrentThread.ManagedThreadId, Task.CurrentId); 13 return string.Format("Return ONE, thread id: {0}", Thread.CurrentThread.ManagedThreadId); 14 }, 15 (int i, ParallelLoopState state, string str) => 16 { 17 Console.WriteLine("Body i {0}, str {1}, thread {2}, task {3}", i, str, Thread.CurrentThread.ManagedThreadId, Task.CurrentId); 18 Thread.Sleep(10); 19 return string.Format("Return TWO, i: {0}", i); 20 }, 21 (str) => 22 { 23 Console.WriteLine("Finally {0}", str); 24 }); 25 } 26 }
运行结果:
4、Foreach方法实现了IEnumerable接口,类似于foreach语句,但是它以异步方式遍历,没有确定的遍历顺序。
1 using System; 2 using System.Threading; 3 using System.Threading.Tasks; 4 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 string[] data = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "zero" }; 10 ParallelLoopResult result = Parallel.ForEach<string>(data, s => 11 { 12 Console.WriteLine(s); 13 }); 14 } 15 }
运行结果:
5、使用Parallel类的Invoke方法可以并行运行多个方法。Invoke方法允许传递一个Action委托数组。
1 using System; 2 using System.Threading; 3 using System.Threading.Tasks; 4 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 Parallel.Invoke(ListenMusic, PlayGame); 10 } 11 12 static void ListenMusic() 13 { 14 Console.WriteLine("Listening music."); 15 } 16 static void PlayGame() 17 { 18 Console.WriteLine("Playing game."); 19 } 20 }
运行结果: