异步委托与线程

时间:2012-07-13 11:13:16

标签: c# asynchronous delegates

用异步代理(回调)替换线程(而不是ThreadPool线程)。

我的场景:为每个客户端生成一个Thread / del.beginInvoke()。

据我说,

原因

  1. 需要通过回叫通知/在Callback中再次呼叫代理
  2. 避免线程开销,(委托使用Threadpool线程)
  3. 传递参​​数(避免转换为对象)并需要从方法返回值。
  4. 如果上述原因错误,请纠正我。

    1. 还有其他原因吗?
    2. 我确实需要用Asynchronous Delegates做一些事情 线程不能?
      3.表现?
    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.
            }
         }
      

      从上面哪个选项会是最好的。表现?

1 个答案:

答案 0 :(得分: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做好准备,它引入了async / await关键字。