Pregunta

Estoy teniendo un comportamiento extraño en una aplicación que me ha sido desconcertante.

creo un hilo, llamémoslo trabajador, que es responsable de manejar las solicitudes de comunicación. Los clientes escriben en una tubería, mientras que el hilo consume las solicitudes y enviar mensajes.

Ahora, el bucle principal de la rosca tiene algo como esto:

lock(this)
{
  object_id = Transport.BeginSend(xxx, xxx, callback, yyy)
  clientsObjects[object_id] = client_id;
}

Ahora la devolución de llamada tiene que acceder al client_id (es un poco más complicado que lo que he escrito, pero la cosa es que la devolución de llamada recibe el object_id, acaba de asumir BeginSend es una llamada a UdpClient.BeginSend

void Callback(IAsyncResult ar)
{
  State st = (State)ar;
  lock(this)
  {
    client_id = clientsObjects[st.object_id]
  }
}

Cerraduras están allí porque la devolución de llamada puede disparar tan rápido que lo que realmente sucede antes clientsObjects[object_id] = client_id; puede ejecutar ...

Ok, ahora .. el problema es que es sin funcionar, bien que funciona ahora y entonces ... ¿por qué? Si trazo los ManagedThreadIds de los hilos que están ejecutando la BeginSend y el que se está ejecutando la devolución de llamada me parece que a veces, tienen la misma ThreadId !!

¿Es posible? ¿Cómo puede suceder? Cualquier sugerencia acerca de lo que estoy haciendo mal?

Comentario: Código real no es exactamente así, Transporte es una envoltura alrededor de la UDPClient que permite cambiar fácilmente la capa de transporte, las cerraduras no son realmente cerraduras pero spinlocks ... pero el concepto en sí es más o menos lo que yo' he escrito.

¿Fue útil?

Solución

Aquí es un artículo antiguo que habla acerca de la función Stream.BeginRead () que efectivamente realiza de forma síncrona, asíncrona no como era de esperar. El artículo es de 2004, así que estoy asumiendo que es en referencia a .NET 1.0 / 1.1. El artículo no se refiere específicamente a UdpClient.BeginSend (), pero a menudo me he preguntado si las funciones BeginXXX en la materia zócalo tienen el mismo comportamiento a veces, especialmente si hay datos para ser leídos inmediatamente. Podría valer la pena comprobar la web para ver si esto es una posibilidad.

¿Es posible pasar el client_id a la función de devolución de llamada a través del parámetro de estado de la función BeginSend ()?

   object_id = Transport.BeginSend(xxx, xxx, Callback, client_id);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top