通常情况下,如果需要异步执行一个耗时的操作,我们会新起一个线程,然后让这个线程去执行代码。但是对于每一个异步调用都通过创建线程来进行操作显然会对性能产生一定的影响,同时操作也相对繁琐一些。.NET 中可以通过委托进行方法的异步调用,就是说客户端在异步调用方法时,本身并不会因为方法的调用而中断,而是从线程池中抓取一个线程去执行该方法,自身线程(主线程)在完成抓取线程这一过程之后,继续执行下面的代码,这样就实现了代码的并行执行。使用线程池的好处就是避免了频繁进行异步调用时创建、销毁线程的开销。
当我们在委托对象上调用BeginInvoke()时,便进行了一个异步的方法调用。调用 EndInvoke() 时就可以获得委托的返回值。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Client application is starting!");
Thread.CurrentThread.Name = "Main Thread";
Cal cal = new Cal();
AddDelegate del = new AddDelegate(cal.Add);
// 需要保存 IAsyncResult 对象以便后边条用EndInvoke方法时作参数传递
IAsyncResult asyncResult = del.BeginInvoke(5, 6, null, null);
// 做某些其它的事情,模拟需要执行 3 秒钟
for (int i = 1; i <= 3; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(i));
Console.WriteLine("{0}: Client executed {1} second(s).", Thread.CurrentThread.Name, i);
}
// 传递 IAsyncResult 对象
int rtnVal = del.EndInvoke(asyncResult);
Console.WriteLine("Result: {0}\n", rtnVal);
Console.WriteLine("\nPress any key to exit...");
Console.ReadLine();
}
public delegate int AddDelegate(int a, int b);
public class Cal
{
public int Add(int a, int b)
{
if (Thread.CurrentThread.IsThreadPoolThread)
{
Thread.CurrentThread.Name = "Pool Thread";
}
Console.WriteLine("Method invoked!");
// 做某些其它的事情,模拟需要执行 2 秒钟
for (int i = 0; i < 2; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(1));
Console.WriteLine("{0}: Add executed {1} second(s).", Thread.CurrentThread.Name, i);
}
Console.WriteLine("Method complete!");
return a + b;
}
}
}
}