异步编程
从Thread说起
考虑到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,因为创建线程需要消耗时间。
Parallel
相比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
除了用信号量来解决异步问题,还可以用lock语句来锁住争抢资源。
信号量强调任务之间的协作关系,锁强调任务之间的争抢关系。信号量和锁可以并存,并不是互斥的。

浙公网安备 33010602011771号