1

我正在使用 UdpClient (c++/cli),我使用明显的 BeginReceive 启动我的监听器。

System::Void CUdpTransmitter::StartListener() {
  ...
  m_UdpClient->BeginReceive ( gcnew System::AsyncCallback(ReceiveCallback), this );
}

ReceiveCallback 应该在最后开始新的 AsyncCallback。是否有任何性能优势或任何其他理由将 AsyncCallback 存储在成员变量中,而不是在每次调用时分配一个新的?线程安全呢?比较以下变体:

System::Void CUdpTransmitter::ReceiveCallback1( System::IAsyncResult ^ asyncResult ) {
  m_UdpClient->EndReceive();
  // parse received data (not time consumpting)
  ...
  if (! exit) {
    m_UdpClient->BeginReceive ( gcnew System::AsyncCallback(ReceiveCallback), self );
  }
}
public ref class CUdpTransmitter {
  AsyncCallback ^ m_callback; // store AsyncCallback in a member variable, it will be initized in constructor... gcnew System::AsyncCallback(ReceiveCallback2)
  System::Void CUdpTransmitter::ReceiveCallback2( System::IAsyncResult ^ asyncResult ) {
    m_UdpClient->EndReceive();
    // parse received data (not time consumpting)
    ...
    if (! exit) {
      // start receiving, reuse the member variable and avoid gcnew
      m_UdpClient->BeginReceive ( m_callback, self );
    }
  }
}

感谢您的时间和回答。

4

1 回答 1

2

代表是线程安全的,所以不用担心。(委托在创建后是不可变的,任何从多播委托中添加或删除委托的方法实际上都返回了一个新的多播委托。)

实例化委托对象和垃圾收集它们有一个非常小的性能损失,所以如果你经常使用这个委托,那么使用 m_callback。然而,正如我所说,这是一个非常小的惩罚,除非你每秒执行几百万次。

如果你不经常这样做,并且你想清理你的代码并减少类成员的闲置,那么每次都实例化回调。

于 2012-11-08T19:01:05.520 回答