首页 新闻 会员 周边

重新开一个线程和委托的异步谁更快一些?

0
悬赏园豆:5 [已解决问题] 解决于 2011-11-16 18:55

我想问一下在一般情况下,用例子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);

悟行的主页 悟行 | 专家六级 | 园豆:12559
提问于:2011-11-16 16:55
< >
分享
最佳答案
1

1,异步委托也是新开一个线程

2,不能说他们谁快,只能说在哪种场合更适合用。异步请求一般用在IO等耗时操作上,他的好处是函数调用立即返回,相应的工作线程立即返还给系统以供重用。多线程是用来并发的执行多个任务。

收获园豆:2
LCM | 大侠五级 |园豆:6876 | 2011-11-16 17:24

我看别人的博客,有好多说异步委托也不是新开一个线程。不知道是怎么搞的。

悟行 | 园豆:12559 (专家六级) | 2011-11-16 17:42

@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 | 园豆:6876 (大侠五级) | 2011-11-16 18:47

@LCM: 多谢了。

悟行 | 园豆:12559 (专家六级) | 2011-11-16 18:53
其他回答(2)
0

你的例子2不是异步的,因为EndInvoke阻塞当前线程。如果你是用BeginInvoke+CallBack的方式,那么本质上也是一个新的线程,因此两者的差异微乎其微了。我比较倾向于后者或者线程池,因为比较轻量级,可以省心好多事情。给一个委托异步调用的代码吧:

Action doSomething = delegate
{
//耗时操作在这里
};

doSomething.BeginInvoke( _ =>
{
//结束时的代码
}, null);
收获园豆:2
水牛刀刀 | 园豆:6350 (大侠五级) | 2011-11-16 17:12

 f.EndInvoke(result);是结束当前异步吧,如果没有他,怎么得到返回值呢。

支持(0) 反对(0) 悟行 | 园豆:12559 (专家六级) | 2011-11-16 17:20

@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");
支持(0) 反对(0) 水牛刀刀 | 园豆:6350 (大侠五级) | 2011-11-16 17:27
0

有2点要说……
1、关于你第二个例子:
  调用BeginInvoke方法之后立即调用EndInvoke,这样就使调用线程进入睡眠状态,等待操作完成。
  也就是你第二个例子中虽然用到了线程,但是却没有达到异步的效果,还没有直接一个线程来得快。
2、BeginInvoke方法将操作加入线程池的队列,也就是说异步委托实际上是用的线程池。
 那显然,池应该快一些,因为省了线程创建和销毁的开销。

收获园豆:1
Higel | 园豆:464 (菜鸟二级) | 2011-11-16 17:39

我做的时候中间是有个方法的:CallBack();,我就没有把这个方法而已贴上来,不好意思。

支持(0) 反对(0) 悟行 | 园豆:12559 (专家六级) | 2011-11-16 17:40
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册