2012-07-13 140 views
7

用异步委托(回调)替换线程(不是ThreadPool线程)。异步委托与线程

我的情景:为每个客户端产生一个线程/ del.beginInvoke()。

据我,

原因

  1. 需要通过回拨/呼叫代理通知再次回调
  2. 避免线程开销,(代表使用线程池线程)
  3. 传递参数(避免投射到对象)并需要从方法返回值。

如果上述原因错误,请纠正我。

  1. 是否有其他原因?
  2. 什么情况下,我确实需要做一些与异步代表 线程不能?
    3.性能?

public delegate void SendCallbackType(); 

    SendCallbackType senderdel= new SendCallbackType(SendData); 

    public void StartSend() // This method Could be Called more than 700 times (Thread per Client) 
    { 
     senderdel.BeginInvoke(SendCallback,null); 
        // (or) 
     Thread t = new Thread(new ThreadStart(ThreadSend)); 
     t.IsBackground = true; 
     t.Start(); 
    } 

    //Async Delegate 
    void SendData() 
    { 
     string data = QueData.DeQueue(); 
     RaiseOnData(data); // Raise to event. 
    } 
    void SendCallback(IAsyncResult ar) 
    { 
     senderdel.BeginInvoke(SendCallback, null); 
    } 

//Thread 
    void ThreadSend() 
    { 
     while (true) 
     { 
     string data = QueData.DeQueue(); 
     RaiseOnData(data); // Raise to event. 
     } 
    } 

从上面的哪个选项将是最好的。性能?

回答

10

您的推理是正确的。异步委托使用线程池中的线程,因此与手动创建线程相比,它们应该更快。在ASP.NET应用程序中,请小心。因为您将耗尽ASP.NET通常用于处理请求的工作线程,并且您的应用程序可能会很快耗尽服务功能。

异步委托对于CPU密集型任务来说很好。对于I/O密集型任务(例如读取流,数据库调用和Web服务调用),您应该使用由相应类(Stream,SqlConnection,WebClient,...)直接提供的BeginXXX,EndXXX方法。这样,在冗长的I/O操作中,您根本没有使用任何线程。您正在使用I/O Completion Ports这是I/O绑定任务中最好的。它将比任何线程和线程池的性能更高,资源更便宜。

所以总结:

  • 对于I/O密集型任务使用I/O完成端口。如果I/O密集型任务被封装在一个写得不好的库中,而这个库不提供这种可能性,那么就使用.NET 4.0中引入的TPL。
  • 对于CPU密集型任务,使用.NET 4.0中引入的TPL。

如果您没有.NET 4.0使用线程池,除非您正在编写一个ASP.NET应用程序,在这种情况下,您可能会诉诸手动线程创建。

一般来说,开始使用TPL并将您的方法定为任务是一种很好的做法,以便您可以使用引入了异步/等待关键字的.NET 4.5。

+0

@ Darin:谢谢你的回复。这里的情况是Windows应用程序,我认为纯粹是CPU密集型任务,当产生1000线程vs 1000 del.begininvoke()调用 – 2012-07-13 12:04:30

+0

@MSK时性能如何,在这种情况下肯定要和TPL一起使用,如果您使用的是旧版本的。 NET使用线程池(ThreadPool,BackgroundWorker,Async委托,... =>它们都将以ThreadPool结束)。在这种情况下不要手动产生线程。 – 2012-07-13 12:07:10

+0

@达林:我不需要火,忘了。在这里我需要一个专门的线程去队列(不管ThreadPool),同时它是一个长时间运行的进程。 – 2012-07-13 12:36:52