我想问一下在一般情况下,用例子1还是用例子2,让程序快一些?
例子1:
Thread t = new Thread(new ThreadStart(Method));
t.Start();
例子2:
Func<int, int> f = new Func<int, int>(Demo);
IAsyncResult result = f.BeginInvoke(99, null, null);
int i = f.EndInvoke(result);
1,异步委托也是新开一个线程
2,不能说他们谁快,只能说在哪种场合更适合用。异步请求一般用在IO等耗时操作上,他的好处是函数调用立即返回,相应的工作线程立即返还给系统以供重用。多线程是用来并发的执行多个任务。
我看别人的博客,有好多说异步委托也不是新开一个线程。不知道是怎么搞的。
@PursueZhang: 是不是这样的,咱们做个小测试不就明白了。就用上楼的异步委托代码,把线程编号写出来,看是不是开的新线程
static void Main(string[] args)
{
Console.WriteLine("1,Thread ID:#{0},Is PoolThread?{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
Func<int> func = delegate
{
Console.WriteLine("sleep 5 seconds...");
Console.WriteLine("2,Thread ID:#{0},Is PoolThread?{1}",Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(5000);
return 100;
};
var r = func.BeginInvoke(s =>
{
var result = func.EndInvoke(s);
Console.WriteLine("3,Thread ID:#{0},Is PoolThread?{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
Console.WriteLine(result);
}, null);
Console.WriteLine("1,Thread ID:#{0},Is PoolThread?{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
Console.WriteLine("main thread exit");
Console.ReadKey();
}
结果如下:
这说明异步委托其实就是开启一个新的线程来执行我们的方法,并且这个线程来自线程池。
@LCM: 多谢了。
你的例子2不是异步的,因为EndInvoke阻塞当前线程。如果你是用BeginInvoke+CallBack的方式,那么本质上也是一个新的线程,因此两者的差异微乎其微了。我比较倾向于后者或者线程池,因为比较轻量级,可以省心好多事情。给一个委托异步调用的代码吧:
Action doSomething = delegate
{
//耗时操作在这里
};
doSomething.BeginInvoke( _ =>
{
//结束时的代码
}, null);
f.EndInvoke(result);是结束当前异步吧,如果没有他,怎么得到返回值呢。
@PursueZhang: 写在【//结束时的代码里】。我更你个更详细的例子看看吧。
Func<int> func = delegate
{
Console.WriteLine("sleep 5 seconds...");
Thread.Sleep(5000);
return 100;
};
var result = func.BeginInvoke(s =>
{
var result = func.EndInvoke(s);
Console.WriteLine(result);
}, null);
//func.EndInvoke(result);
Console.WriteLine("main thread exit");
有2点要说……
1、关于你第二个例子:
调用BeginInvoke方法之后立即调用EndInvoke,这样就使调用线程进入睡眠状态,等待操作完成。
也就是你第二个例子中虽然用到了线程,但是却没有达到异步的效果,还没有直接一个线程来得快。
2、BeginInvoke方法将操作加入线程池的队列,也就是说异步委托实际上是用的线程池。
那显然,池应该快一些,因为省了线程创建和销毁的开销。
我做的时候中间是有个方法的:CallBack();,我就没有把这个方法而已贴上来,不好意思。