概念
说异步前,首先讲讲这些概念,异步/同步、多线程。
异步:是指呼叫另一操作后,不等待其结果,继续执行之后的操作,若之后没有其他操作,当前线程将进入睡眠状态,而CPU时间将有机会切至其他线程。在异步操作完成后通过回调函数的方式获取通知与结果。异步的实现方式有多种,如多线程与完成端口。多线程将异步操作放入另一线程中运行,通过轮询或回调方法得到完成通知;完成端口,由操作系统接管异步操作的调度,通过硬件中断,在完成时触发回调方法,此方式不需要占用额外线程。
同步:与异步相对应。
多线程:一般指同一进程中多个线程(包含其数据结构、上下文与代码片段)协作运行。在多核计算机中多个线程将有机会同时运行于多个核上,如果线程中进行的是计算,则行成并行计算。
.NET中的异步
多线程
概念中提到的用多线程方式实现异步操作,可以使用各种多线程的接口。参照后文中.NET中的多线程。
Classic Async Pattern(CAP) (BeginXXX & EndXXX)
委托(delegate),文件读写(FileStream)等等许多的类里面都包含了BeginXXX & EndXXX的异步接口,利用这些接口即可以实现异步编程。但是这个模型里面到底是使用多线程还是完成端口却取决于具体的实现,委托的(BeginInvoke & EndInvoke)是基于多线程实现。而FileStream要使用完成端口也要传入FileOptions.Asynchronous提前告诉你将要使用异步IO读取,否则将会使用默认的多线程实现。
Event-based Async Pattern(EAP)(XXXAsync & XXXComplete)
.NET Framework除了提供上面这种编程模式外,还提供了基于事件的异步编程模式。比如WebClient的很多方法就提供了异步版本,比如DownloadString方法。
同步版本:
public string DownloadString(string url);
异步版本:
public void DownloadStringAsync(string url);
public event DownloadStringCompleteEventHandler DownloadStringComplete;
Task-based Asynchronous Pattern(TAP)(async & await)
以上两种异步编程模型(CAP & EAP)都将异步实现分成了两部分:一部分发起异步操作,另一部分获得结果。如果多个异步需要顺序执行的时候,那么就会造成一个异步回调里嵌套另一个异步调用,代码变得非常混乱。
而TAP就是为了解决这个回调灾难的。而且还引入了两个新的语言关键字用于方便用户编写异步编程代码(async & await)。
.NET中的多线程
Thread
托管线程的基础类。
ThreadPool
内部实现的线程池,循环使用线程,避免线程频繁的创建,提高效率。
Task
使用内部实现的线程池。更方便的线程创建,异常捕获,多任务同步。
线程锁
独占锁
Monitor & lock
互斥锁
Mutex 可以实现跨进程的锁。
读写锁
ReaderWriterLock,读写(Reader-Writer)两种请求,按照请求到达的顺序,一共有四种:
Reader-Reader,第二个不需等待,直接获得读控制权;
Reader-Writer,第二个需要等待第一个调用ReleaseReaderLock()释放读控制权后,才能获得写控制权;
Writer-Writer,第二个需要等待第一个调用ReleaseWriterLock()释放写控制权后,才能获得写控制权;
Writer-Reader,第二个需要等待第一个调用ReleaseWriterLock()释放写控制权后,才能获得读控制权。