¿Causa de una alta pérdida de paquetes UDP en localhost?

En mi aplicación WPF 4.0, tengo una escucha UDP implementada como se muestra a continuación. En mi PC con Windows 7, ejecuto el servidor y el cliente en localhost .

Cada datagtwig recibido es una línea de escaneo de un bitmap más grande, por lo que después de que se hayan recibido todas las líneas de escaneo, el bitmap se muestra en el hilo de la UI . Esto parece funcionar. Sin embargo, ocasionalmente faltan entre 1 y 50% las líneas de escaneo. Esperaría esto en una conexión de red débil, pero no cuando se ejecuta localmente.

¿Qué puede causar la pérdida del paquete UDP con el siguiente fragmento de código?

 IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, PORT); udpClient = new UdpClient(endPoint); udpClient.Client.ReceiveBufferSize = 65535; // I've tried many different sizes... var status = new UdpStatus() { u = udpClient, e = endPoint }; udpClient.BeginReceive(new AsyncCallback(UdpCallback), status); private void UdpCallback(IAsyncResult ar) { IPEndPoint endPoint = ((UdpStatus)(ar.AsyncState)).e; UdpClient client = ((UdpStatus)(ar.AsyncState)).u; byte[] datagram = client.EndReceive(ar, ref endPoint); // Immediately begin listening for next packet so as to not miss any. client.BeginReceive(new AsyncCallback(UdpCallback), ar.AsyncState); lock (bufferLock) { // Fast processing of datagram. // This merely involves copying the datagram (scanline) into a larger buffer. // // WHEN READY: // Here I can see that scanlines are missing in my larger buffer. } } 

Si pongo un System.Diagnostics.Debug.WriteLine en mi callback, la pérdida del paquete aumenta dramáticamente. Parece que un pequeño retraso de milisegundos dentro de esta callback causa problemas. Aún así, el mismo problema se ve en mi versión de lanzamiento.

ACTUALIZAR

El error se vuelve más frecuente cuando enfatizo un poco la interfaz de usuario. ¿ UdpClient ejecuta la instancia de UdpClient en el hilo principal?

Para evitar el problema del locking de subprocesos, intente este enfoque que utiliza el nuevo método de recepción de puerto de finalización de E / S:

 private void OnReceive(object sender, SocketAsyncEventArgs e) { TOP: if (e != null) { int length = e.BytesTransferred; if (length > 0) { FireBytesReceivedFrom(Datagram, length, (IPEndPoint)e.RemoteEndPoint); } e.Dispose(); // could possibly reuse the args? } Socket s = Socket; if (s != null && RemoteEndPoint != null) { e = new SocketAsyncEventArgs(); try { e.RemoteEndPoint = RemoteEndPoint; e.SetBuffer(Datagram, 0, Datagram.Length); // don't allocate a new buffer every time e.Completed += OnReceive; // this uses the fast IO completion port stuff made available in .NET 3.5; it's supposedly better than the socket selector or the old Begin/End methods if (!s.ReceiveFromAsync(e)) // returns synchronously if data is already there goto TOP; // using GOTO to avoid overflowing the stack } catch (ObjectDisposedException) { // this is expected after a disconnect e.Dispose(); Logger.Info("UDP Client Receive was disconnected."); } catch (Exception ex) { Logger.Error("Unexpected UDP Client Receive disconnect.", ex); } } }