Utilizzando ThreadPool.QueueUserWorkitem per aprire una connessione TCPClient e leggere i dati in ASP.NET e SIGNI
-
27-10-2019 - |
Domanda
Ho letto un paio di post su SignalR e ho pensato a un progetto di test divertente che avrei potuto creare un'applicazione Web per pollicare il mio ricevitore Onkyo per lo stato e visualizzare i risultati in un browser. Per un test iniziale, sono stato in grado di inviare correttamente l'ora corrente sul server al client utilizzando questo codice in Application_Start:
ThreadPool.QueueUserWorkItem(_ =>
{
dynamic clients = Hub.GetClients<KudzuHub>();
while (true)
{
clients.addMessage(DateTime.Now.ToString());
Thread.Sleep(1000);
}
});
Nel client JavaScript, ho il seguente codice:
// 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();
Quindi tutto questo funziona bene. Ogni secondo, ottengo un nuovo elemento dell'elenco contenente la data e l'ora del server corrente.
Ora, quando aggiungo questo codice per leggere i dati dal ricevitore Onkyo, si rompe: (ancora in 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
}
});
Ho impostato un punto di rottura e ho attraversato il codice. Arriva a questa linea e poi ritorna.
clientSockStream.Read(bytes, 0, (int)tcpClient.ReceiveBufferSize);
Non finisce mai il resto del codice per inviare il messaggio al client. Che cosa sto facendo di sbagliato?
Grazie.
Soluzione
Vorrei apportare alcune modifiche strutturali al tuo loop per consentire al tempo di rispondere al ricevitore, rimuovere il sovraccarico di recuperare la configurazione ogni 50 millisecondi e pulire il flusso di rete aperta:
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();
}
}
});