2012-11-08 3 views
1

UdpClient (C++/cli)를 사용 중이므로 확실한 BeginReceive를 사용하여 리스너를 시작합니다.AsyncCallback을 멤버 변수에 저장하여 새로운 멤버를 생성하는 것보다 효과적입니다.

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); 
    } 
    } 
} 

시간을 내 주셔서 감사합니다.

답변

1

대리인은 스레드로부터 안전하므로 걱정할 필요가 없습니다. (대리자는 생성 후에 불변이며, 멀티 캐스트 대리자로부터 대리자를 추가하거나 제거하는 모든 메서드는 실제로 새로운 멀티 캐스트 대리자를 반환합니다.)

대리자 개체를 인스턴스화하고이를 가비지 수집하는 데 아주 적은 성능 저하가 있습니다. 이 대리자를 자주 사용하고 m_callback을 사용하십시오. 그러나, 내가 말했듯이, 이것은 초당 수백만 번하는 경우가 아니면 아주 사소한 처벌입니다.

이 작업을 자주 수행하지 않고 코드를 정리하고 클래스 멤버가 줄고 싶다면 매번 콜백을 인스턴스화하십시오.

+0

음, MTU 1500 바이트를 고려할 때 6 카메라 (VGA 해상도 @ 30fps, 회색조 8 비트)의 데이터를 파싱합니다. 약 37000 패킷/s를 의미합니다. 대답에 따르면, 그것은 m_callback을 저장할 가치가없는 것 같습니다. 그러나 어쨌든, 경험이 부족했기 때문에 m_callback을 이런 방식으로 재사용 할 수 있는지 알고 싶었습니다. 대답은 Thx. – dousin