2011-10-24 53 views
5

Podría ayudar a que me deshaga de esta excepción:¿Cómo detengo SocketException: "Se ha interrumpido una operación de bloqueo mediante una llamada a WSACancelBlockingCall"?

System.Net.Sockets.SocketException: "Una operación de bloqueo fue interrumpida por una llamada a WSACancelBlockingCall"

  1. Lo el siguiente código: envía un mensaje UDP al servidor y obtiene la respuesta (NAK o ACK)

  2. Código que arroja una excepción: m_receiveBytes = m_receiver.Receive(ref m_from);

Código:

public partial class _Default : System.Web.UI.Page 
{ 
    static readonly object lockScheduleIem = new object(); 
    IPAddress m_AddressSend; 
    IPAddress m_AddressRecieve; 
    int m_groupPortSend; 
    int m_groupPortReceive; 
    IPEndPoint m_IPAddressSend; 
    IPEndPoint m_IPAddressReceive; 
    Byte[] m_receiveBytes; 
    Thread m_thread; 
    UdpClient m_receiver; 
    ManualResetEvent m_mre; 
    UdpClient m_sender; 
    IPEndPoint m_from; 

    protected void Page_Init(object sender, EventArgs e) 
    { 
     m_AddressSend = IPAddress.Parse("10.43.60.177"); 
     m_AddressRecieve = IPAddress.Parse("10.43.60.99"); 

     int.TryParse("60200", out m_groupPortSend); 
     int.TryParse("206", out m_groupPortReceive); 

     m_IPAddressSend = new IPEndPoint(m_AddressSend, m_groupPortSend); 
     m_IPAddressReceive = new IPEndPoint(m_AddressRecieve, m_groupPortReceive); 

     m_mre = new ManualResetEvent(false); 
     m_from = new IPEndPoint(IPAddress.Any, 0); 
    } 
    protected void Page_Load(object sender, EventArgs e) 
    { 

    } 

    protected void Button1_Click(object sender, EventArgs e) 
    { 
     try 
     { 
      TimeSpan timeout; 
      timeout = new TimeSpan(0, 0, 0, 0, 5000); 
      m_sender = new UdpClient(); 
      m_receiveBytes = null; 
      m_receiver = new UdpClient(m_IPAddressReceive); 
      m_thread = new Thread(new ThreadStart(ThreadProc)); 
      m_thread.Start(); 
      string str = string.Empty; 
      using (StreamReader sr = new StreamReader(@"C:\UDPmsgArchive\UDPmsg_Of_2011_10_18_13_7_33_968_634545400539687500.xml")) 
       str = sr.ReadToEnd(); 
      byte[] XMLbytes = Encoding.ASCII.GetBytes(str); 
      m_sender.Send(XMLbytes, XMLbytes.Length, m_IPAddressSend); 

      m_mre.WaitOne(timeout, true); 
      m_mre.Reset(); 
      m_receiver.Close(); 

      if (m_receiveBytes != null) 
       Response.Write(Encoding.ASCII.GetString(m_receiveBytes, 0, m_receiveBytes.Length)); 
      else 
       Response.Write("string.Empty"); 
     } 
     catch (Exception ex) 
     { 
      Response.Write(ex.ToString()); 
     } 
    } 

    public void ThreadProc() 
    { 
     try 
     { 
      m_receiveBytes = m_receiver.Receive(ref m_from); // ERROR HERE 
      m_mre.Set(); 
      m_receiver.Close(); 
     } 
     finally 
     { 
      m_mre.Set(); 
     } 
    } 
} 

Respuesta

4

Si estoy leyendo el código de la derecha, que está empezando un hilo para recibir un mensaje UDP. Si recibe el mensaje, establece un evento. El hilo principal inicia el hilo y luego espera hasta cinco segundos para que se establezca el evento. Si el evento no se establece dentro de ese tiempo, el hilo principal destruye el receptor que el hilo está esperando.

Definitivamente va a lanzar una excepción.

Si espera para eliminar la excepción, modificar ThreadProc

try 
{ 
    // do stuff here 
} 
catch (SocketException) // or whatever the exception is that you're getting 
{ 
} 

Yo sugeriría que no incluir la llamada m_mre.Set() en una sección finally. El hilo principal llama al Reset en el evento una vez completada la espera, haya o no un tiempo de espera. Si el subproceso llama Set en el último, el estado del evento se activa cuando se produce un tiempo de espera, porque ocurre lo siguiente:

main thread calls Reset() 
main thread calls Close() on the client 
ThreadProc calls Set() in the finally 

En su lugar, cambiar su código hilo principal a tener este aspecto:

if (m_mre.WaitOne(timeout, true)) 
{ 
    // event was set by the thread proc 
    // process the received data 
    // and reset the event 
    m_mre.Reset(); 
} 
else 
{ 
    // A timeout occurred. 
    // Close the receiver 
    m_receiver.Close(); 
} 

Dicho esto, realmente no tienes que girar un hilo para hacer esto. Por el contrario, podría utilizar las capacidades asincrónicas de UdpClient. Algo así como:

// Set timeout on the socket 
m_receiver.Client.ReceiveTimeout = 5000; 
try 
{ 
    IAsyncResult ir = m_receiver.BeginReceive(null, null); 
    m_receivedBytes = m_receiver.EndReceive(ir, m_receiver.Client.RemoteEndPoint); 
    // process received bytes here 
} 
catch (SocketException) 
{ 
    // Timeout or some other error happened. 
} 
+0

Realmente apreciamos, voy a tratar su sugerencia, y te voy a dar retroalimentación – user852194

+0

Hola Jim i probar su lógica más adelante, pero por desgracia todavía tiene el mismo error. – user852194

+0

@ user852194: ¿Cuál es la excepción exacta que recibe? ¿La 'captura' realmente atrapa la excepción? –

Cuestiones relacionadas