首先来看一个简单的例子:
这个例子是先将水放在炉子上,然后让水烧着,小文接下去整理家务,烧水是异步。当水烧开后,烧水线程通知小文水烧开了,小文放下手中的家务,将热水灌到热水瓶,然后继续整理家务,主线程继续运行。
- 小明在烧水,等水烧开以后,将开水灌入热水瓶,然后开始整理家务
- 小文在烧水,在烧水的过程中整理家务,等水烧开以后,放下手中的家务活,将开水灌入热水瓶,然后继续整理家务
这也是日常生活中很常见的情形,小文的办事效率明显要高于小明。从C#程序执行的角度考虑,小明使用的同步处理方式,而小文则使用的异步处理方式。
同步处理方式下,事务是按顺序一件一件处理的;而异步方式则是,将子操作从主操作中分离出来,主操作继续进行,子操作在完成处理的时候通知主操作。
class Program
{
static TimeSpan Boil()
{
Console.WriteLine("水壶:开始烧水...");
Thread.Sleep(6000);
Console.WriteLine("水壶:水已经烧开了!");
return TimeSpan.MinValue;
}
delegate TimeSpan BoilingDelegate();
static void Main(string[] args)
{
Console.WriteLine("小文:将水壶放在炉子上");
BoilingDelegate d = new BoilingDelegate(Boil);
IAsyncResult result = d.BeginInvoke(BoilingFinishedCallback, null);
Console.WriteLine("小文:开始整理家务...");
for (int i = 0; i < 20; i++)
{
Console.WriteLine("小文:整理第{0}项家务...", i + 1);
Thread.Sleep(1000);
}
}
static void BoilingFinishedCallback(IAsyncResult result)
{
AsyncResult asyncResult = (AsyncResult)result;
BoilingDelegate del = (BoilingDelegate)asyncResult.AsyncDelegate;
del.EndInvoke(result);
Console.WriteLine("小文:将热水灌到热水瓶");
Console.WriteLine("小文:继续整理家务");
}
}
这个例子是先将水放在炉子上,然后让水烧着,小文接下去整理家务,烧水是异步。当水烧开后,烧水线程通知小文水烧开了,小文放下手中的家务,将热水灌到热水瓶,然后继续整理家务,主线程继续运行。
代码中,BoilingDelegate为烧水的委托,Boil来具体实现怎么烧水,BeginInvoke来异步开始烧水,烧开后,回调BoilingFinishedCallback,方法中,调用EndInvoke,该方法会将异步线程终止,同时返回委托的返回值,然后告诉小文水烧开了,让他灌水
注意:
- 异步函数由线程完成,这个线程是.NET线程池中的线程
- 通常情况下,.NET线程池拥有500个线程(当然这个数量可以设置),每当调用BeginInvoke开始异步处理时,异步处理函数就由线程池中的某个线程负责执行,而用户无法控制具体是由哪个线程负责执行
- 由于线程池中线程数量有限,因此当池中线程被完全占用时,新的调用请求将使函数不得不等待空余线程的出现。此时,程序的效率会有所影响