考虑到leetcode上一道题:使用异步编程,依次输出first,second,thrid
public class Foo { bool syncFirst = true; bool syncSecond=false; bool syncThird=false; public Foo() { } public void First(Action printFirst) { // printFirst() outputs "first". Do not change or remove this line. while (true) { if (syncFirst) { printFirst(); syncSecond = true; break; } } } public void Second(Action printSecond) { // printSecond() outputs "second". Do not change or remove this line. while (true) { if (syncSecond) { printSecond(); syncThird = true; break; } } } public void Third(Action printThird) { // printThird() outputs "third". Do not change or remove this line. while (true) { if (syncThird) { printThird(); break; } } } }
上述代码是很传统的基于信号量的异步处理。
var foo = new Foo(); Action first = () => { foo.First(() => Console.WriteLine("printing first")); }; Action second = () => { foo.Second(() => Console.WriteLine("printing second")); }; Action third = () => { foo.Third(() => Console.WriteLine("printing third")); }; Thread t1 = new Thread(new ThreadStart(first)); Thread t2 = new Thread(new ThreadStart(second)); Thread t3 = new Thread(new ThreadStart(third)); t1.Start(); t2.Start(); t3.Start();
main函数代码如上。
first等函数通过接受无参Action
委托注入具体操作。死循环检查信号量,如果检测到就执行并退出。
Thread的初始化需要通过ThreadStart
指定线程执行的任务,ThreadStart
实际上是个无参Action
委托。
通过Start来执行线程中的任务。
Console.WriteLine( t1.ThreadState.ToString()+t1.IsBackground);
查看线程状态,和是否为Background线程。
Background线程不同于Forground线程,进程如果没有后者将会被CLR直接杀死。
t1.Suspend(); t1.Resume();
除了Start还有悬停和重启。
C#中不建议使用Thread,因为创建线程需要消耗时间。
相比Thread,编译器直接将 是否创建线程,使用哪个线程托管给了操作系统。Parallel本意为平行,使用其方法可以创造多个并行线程执行任务。
List<Action> a = new List<Action>(); for (int i = 0; i < 10; i++) { var j = i;//非常重要,不然会闭包,所有的结果都是10。 a.Add(new Action(() => Console.WriteLine($"Proceeding: {j}"))); } Parallel.ForEach(a, i => i()); Console.WriteLine(); Parallel.For(0, 10, i => a[i]());
注意ForEach和For的不同:ForEach中的第一个参数是IEnumerable<T>
接口,第二个参数是Action<T>
For中第一个参数是起始值,第二个参数类似于for语句中的i<10;第三个参数是Action<int>
,和for语句非常类似。如果要在For语句循环时控制循环状态,例如:在循环到某个条件时停下,就要使用Action<int,ParallelLoopState>
除了用信号量来解决异步问题,还可以用lock语句来锁住争抢资源。
信号量强调任务之间的协作关系,锁强调任务之间的争抢关系。信号量和锁可以并存,并不是互斥的。