7

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

我的场景:为每个客户端生成一个 Thread/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.
      }
   }

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

4

1 回答 1

10

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

异步委托适用于 CPU 密集型任务。对于 I/O 密集型任务(例如读取流、数据库调用和 Web 服务调用),您应该使用相应类(Stream、SqlConnection、WebClient...)直接提供的 BeginXXX、EndXXX 方法。这样,您在冗长的 I/O 操作期间根本不会使用任何线程。您正在使用I/O 完成端口,这在 I/O 绑定任务方面是最好的。它将比任何线程和线程池的性能和资源便宜几个数量级。

所以总结一下:

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

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

一般来说,开始使用TPL并将您的方法定位为任务是一种很好的做法,这样您就可以为引入 async/await 关键字的 .NET 4.5 做好准备。

于 2012-07-13T11:55:16.670 回答