Uso de ThreadPool.QueUserWorkItem para abrir una conexión TCPClient y leer datos en ASP.NET y SignalR

StackOverflow https://stackoverflow.com/questions/8373081

Pregunta

He leído un par de publicaciones en SignalR y pensé para un proyecto de prueba divertido que podría crear una aplicación web para encuestar a mi receptor Onkyo para el estado y mostrar los resultados en un navegador. Para una prueba inicial, pude enviar el tiempo actual en el servidor al cliente utilizando este código en Application_Start:

ThreadPool.QueueUserWorkItem(_ =>
{               
    dynamic clients = Hub.GetClients<KudzuHub>();
    while (true)
    {                
        clients.addMessage(DateTime.Now.ToString());

        Thread.Sleep(1000);
    }
});   

En el cliente JavaScript, tengo el siguiente código:

// Proxy created on the fly
var kHub = $.connection.kudzuHub;

// Declare a function on the hub so that the server can invoke it
kHub.addMessage = function (message) {
    console.log('message added');
    $('#messages').append('<li>' + message + '</li>');
};

// start the connection
$.connection.hub.start();

Entonces todo eso funciona bien. Cada segundo, obtengo un nuevo elemento de lista que contiene la fecha y hora del servidor actual.

Ahora, cuando agrego este código para leer datos del receptor Onkyo, se rompe: (todavía en Application_Start)

ThreadPool.QueueUserWorkItem(_ =>
{  
    dynamic clients = Hub.GetClients<KudzuHub>();
    try
    {
        while (true)
        {
            string host = ConfigurationManager.AppSettings["receiverIP"].ToString();
            int port = Convert.ToInt32(ConfigurationManager.AppSettings["receiverPort"]);

            TcpClient tcpClient = new TcpClient(host, port);

            NetworkStream clientSockStream = tcpClient.GetStream();

            byte[] bytes = new byte[tcpClient.ReceiveBufferSize];
            clientSockStream.Read(bytes, 0, (int)tcpClient.ReceiveBufferSize);

            tcpClient.Close();

            clients.addMessage(System.Text.Encoding.ASCII.GetString(bytes));
            Thread.Sleep(50);
        }
    }
    catch (SocketException ex)
    {
        // do something to handle the error
    }

});

Establecí un punto de quiebre y atravesé el código. Llega a esta línea y luego regresa.

clientSockStream.Read(bytes, 0, (int)tcpClient.ReceiveBufferSize);

Nunca termina el resto del código para enviar el mensaje al cliente. ¿Qué estoy haciendo mal?

Gracias.

¿Fue útil?

Solución

Haría algunos cambios estructurales en su bucle para permitir que responda el tiempo del receptor, eliminar la sobrecarga de recuperar la configuración cada 50 milisegundos y limpiar la secuencia de red abierta:

ThreadPool.QueueUserWorkItem(_ =>
{  
    dynamic clients = Hub.GetClients<KudzuHub>();
    TcpClient tcpClient = null;
    NetworkStream clientSockStream = null;

    try
    {
        string host = ConfigurationManager.AppSettings["receiverIP"].ToString();
        int port = Convert.ToInt32(ConfigurationManager.AppSettings["receiverPort"]);

        while (true)
        {
            if (tcpClient == null) {
              tcpClient = new TcpClient(host, port);
              clientSockStream = tcpClient.GetStream();
            }

            if (clientSockStream.CanRead) {
                byte[] bytes = new byte[tcpClient.ReceiveBufferSize];
                try {
                   clientSockStream.Read(bytes, 0, (int)tcpClient.ReceiveBufferSize);
                } catch (Exception ex) {
                  // Add some debug code here to examine the exception that is thrown
                }

                tcpClient.Close();
                // Closing the client does not automatically close the stream
                clientSockStream.Close();

                tcpClient = null;
                clientSockStream = null;

                clients.addMessage(System.Text.Encoding.ASCII.GetString(bytes));
            }
            Thread.Sleep(50);
        }
    }
    catch (SocketException ex)
    {
        // do something to handle the error
    } finally {
       if (tcpClient != null) {
         tcpClient.Close();
         clientSockStream.Close();
       }
    } 

});
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top