last day (15 days later) » 

3:59 PM
0
Q: ¿Como levantar un hilo cuando cae?

Aritz BelloTengo un hilo que controla otro hilo, el problema es que necesito que el otro hilo se reinicie cada x tiempo y al intentar iniciarlo de nuevo no puedo hacer que se inicie. System.Threading.ThreadStateException:'Subproceso en ejecución o terminado;no se puede reiniciar.' ¿Hay alguna forma d...

 
Un disparo al aire, pero me parece que el hilo no está teniendo tiempo para iniciarse ya que el while(true) bloquea el hilo principal y se ejecuta muy rápido. Puedes hacer una prueba rápida y meter un Thread.Sleep(1000) al final (pero dentro) del while a ver si dándole un poco de tiempo el hilo ha podido iniciarse? P.D. Te recomendaría otro hilo en lugar del while(true) en el hilo principal, tal vez un BackgroundWorker.
 
No tengo ni idea de como funciona el BackgroundWorker, pero de todas formas le echaré un ojo a ver si veo documentación sobre el tema, es el primer "servicio" que programo y estoy un poco perdido.
 
Si, la he visto, pero me parece que es posible que al hilo no le haya dado tiempo a "nacer" del todo y el IsAlive todavía siga siendo false por lo que entra otra vez. Podrías incluso meter un mensaje por consola simplemente para monitorizar cuantas veces pasa por ahí. Es posible que no sea ese el problema pero mejor si lo descartamos. Si se confirman mis sospechas te intento explicar mejor el por que pasa esto.
 
probablemente tengas razón, creo que ya entiendo lo que dices. La proxima vez que esté en el ordenador donde tengo el programa lo miro, he dejado el programa en ejecucion hasta mañana, a ver si se registran los fallos en el log. Pero es eso, supongo que al ser while(true) no hay tiempo de espera entre cada vuelta en el bucle por lo que lo ejecuta más de una vez y da error. De todas formas, no me ha vuelto a dar ni un fallo, llevaba un par de horas intentando provocarlo sacando el cable de red etc.
 
Coméntanos con lo que sea para que intentemos ayudarte ;)
 
3:59 PM
Pensaba que sí, pero no consigo que el hilo se reinicie. Edito para poner lo que me dice.
El metodo hilo abre un socket a una dirección ip, vía telnet, lanza varios comandos y empieza a recibir información del socket. Lo que pasa es que la sesión abierta en el socket caduca cada X tiempo o pierde conexión cada X tiempo, el socket no me envía ningún mensaje de que se haya perdido la conexión por lo que hilo sigue escuchando al socket, aunque no haya conexión. El socket se abre a otra sede ajena, por lo que no se me ocurre ninguna manera mejor de solucionarlo.
 
Uy! Ha cambiado el cuento desde mi último comentario. El problema que tienes ahora (al contrario que en el otro código que nos enseñaste) es que el hilo se inicia, se muere (no haría falta el abort, debería de morir el solito) y luego lo quieres lanzar otra vez. Eso no se puede/debe hacer. Tienes que hacer que el hilo no muera (ejecución contínua) o volver a crear un hilo nuevo cada vez (lo que me parece un overkill). Para evitar más ediciones y demás, podrías ponernos en el código una representación lo más real posible de tu flujo de hilos actual?
 
Creo que con lo que ya he puesto, adjuntando algo parecido a la clase hilo se puede ver lo que pasa. La única diferencia está en los registros a la BBDD contraseñas y demás que no he puesto, tal vez alguna variable sin inicializar que he dejado por ahí, pero vamos, el hilo no falla en ningún punto.
 
Por confirmar: controladorHilos realmente hace eso que indicas? Inicia un hilo (Start), pone a dormir el hilo que le invoca (Thread.Sleep) y luego fuerza un aborto del hilo (abort) dentro de un while(true)? O eso sigue siendo código de ejemplo que no encaja con tu código actual?
 
Ahora mismo es lo que tengo en mi programa, pero es lo último que he hecho por probar, simplemente podría quitar el abort y demás, dejando controladorHilos con únicamente start de los hilos que en un futuro vaya a poner, por ahora solo está esto. Edito de nuevo para que quede constancia de que eso ya no lo utilizaré, al ver que es algo que no tiene sentido mientras que busco alguna solución para relanzar todo el programa.
De todas formas, estoy empezando a pensar que lo que mi jefe me ha pedido no es viable, simplemente creo que lo acabaré solucionando con el programador de tareas de windows o algo...
 
Continuemos en el chat mejor!
 
3:59 PM
Buenas
 
Buenas!
 
¿Se te ocurre alguna forma más, aunque sea teórica de poder solucionar esto?
 
Como hemos estando dando vueltas, cual es ahora el problema?
 
Vale, te comento
Tengo el metodo hilo, el metodo controladorHilo que controla el hilo y a parte de el tengo el main, que abre el metodo controladorHilo con el hilo.
 
correcto
 
4:02 PM
El metodo hilo abre el socket, como puedes ver en la pregunta. El socket funciona correctamente, sin problemas, guarda los registros en la base de datos y demás.
El problema es que cuando pasa X tiempo, el socket rechaza la conexión.
 
y no provoca ningún tipo de excepción?
 
No provoca ningún tipo de excepción. Simplemente es un listener, que cada vez que recibe datos los procesa
Recibe datos>Hace substring>Guarda en base de datos
 
y cuando no recibe no sabe si es por que "petó" o por que no se están recibiendo datos...
Tienes algún indicio de cuanto tiempo es ese X?
 
Depende de la línea, ya que a través de internet accedemos a otra ip, y parece que hay cortes, o rechaza la conexión, o se cierra la sesión abierta en el socket. Sea como fuere, el proceso sigue abierto en el ordenador.
Por eso estaba pensando, tal vez, si cada hora reinicio el proceso, pueda conseguir que haya la menor perdida de información posible.
 
Una sugerencia tonta. Y si reinstancias TcpClient cada vez?
 
4:07 PM
Creo que no me valdría, ya que estamos registrando un histórico de cantidad de llamadas en espera. Cada vez que abres el socket lanzas el comando queueinfo que abre "algo" (disculpa, no sé que es exactamente lo que hace, ya que no tengo acceso al código, ni al programa, ni a nada) y lo primero que hace es decirte Cola 0 .
 
De ese modo, todo el proceso empieza de nuevo en cada iteración del while. En ese caso daría igual por que es un socket nuevo, es una conexión nueva, así que no se queda abierto el socket durante un largo periodo de tiempo y no tendrías ese problema. O estoy interpretando el código de forma incorrecta?
 
Claro, al ser "Cola 0", en la base de datos habría un montón de registros que no serían reales.
Lo que hace es tratar una información que llega desde un servidor.
Sería una buena solución si al abrir la informacion de colas no me diera el mensaje, pero lamentablemente, me lo da.
 
Creo que me falta algo de información, sobre todo de los mensajes de envío y respuesta para hacerme una idea más concreta.
No obstante, no puedes evitar simplemente el registrar ese mensaje de "Cola 0"?
 
Voy a revisar a ver si podría hacerlo. Pero lo dudo...
De todas formas, dame un momentito, te voy a pasar algo.
Si, sería if (data.contains("queueinfo")){//procesar la línea}. Debes tener en consideración la posibilidad de que en data haya mas de una línea, eso dependerá de varios factores.Y si, para los comandos es igual que si los tecleases, enviando comando + enter (Environment.Newline) — Pikoh Oct 18 at 8:47
tengo esta pregunta, que es justamente como desarrollé lo necesario, a ver si te ayuda un poco. Como te digo, es información "confidencial" y no puedo hablar mucho de ello, es un tema complicado.
 
Pero me ha dado bastante información para entender mejor tu problema y/o lo que necesitas
déjame que le de una vuelta
 
4:18 PM
Como puedes ver, los registro son queueinfo _____ numero
Vale, seguiré mirando a ver si consigo algo, muchas gracias por todo, desde ya.
 
4:29 PM
Tal vez esto pueda ayudar más, la última vez que el programa estuvo funcionando, estuvo trabajando desde por lo menos las 10 de la mañana hasta las 20:37, el próximo intervalo fue de 09:29 hasta las 20:04 y el siguiente desde las 10:00 hasta las 15:03 , no tiene consistencia.
 
vale
 
El programa tiene en 3 días más de 3.000 registros, por lo que, si reiniciaría el TCP en cada una de las veces, serían más de 6.000...
 
después de revisarlo un poco mejor
realmente no, con una ligera modificación
 
¿con un contador?
 
Reiniciar el TCPClient no tiene mucho más impacto que necesitar volver a loguearte
es decir, ese hilo está contínuamente while(true) lanzando un queueinfo al socket
 
4:32 PM
no es así
El hilo lanza una única vez queueinfo
y desde que lanzas queueinfo empieza a recibir datos constantemente.
 
if (data.Contains("Cualquier mensaje recibido del socket"))
{
msg = System.Text.Encoding.ASCII.GetBytes("queueinfo" + Environment.NewLine);
stream.Write(msg, 0, msg.Length);
//Aqui hay inserciones a una BBDD etc. Todo funciona ok.
}
ahí me indica lo contrario
 
El orden exacto es:
Queueinfo > recibe primer registro(queueinfo ____ 0 ) > queueinfo 1/2/3/4....
 
pero escribes en el canal de comunicación queueinfo siempre que te devuelve datos, por lo que contínuamente se los estás pidiendo. O hay algo que no estoy viendo correctamente?
 
No, no es así, en el canal de comunicacion queueinfo se escribe una única vez
Y este empieza a enviar información.
 
pero si data (mensaje recibido por el socket) recibe cualquier dato, vuelves a entrar y vuelves a escribir en el socket queueinfo de nuevo, ejecutando el comando. O esa parte del código no es correcta? if (data.Contains("Cualquier mensaje recibido del socket"))
 
4:37 PM
únicamente es si data.contains("login") hace login+queueinfo , después no vuelve a ejecutarse esa condicional nunca más. Ya que data nunca vuelve a contener login
es login>queueinfo>dato recibido>dato recibido>dato recibido>dato recibido...
Así constantemente
login>queueinfo>dato recibido>dato recibido>dato recibido>dato recibido... (En algún momento se pierde la conexión, deja de recibir datos, el listener sigue activo esperando datos. )
 
vale, entonces el código de ejemplo que tienes puesto en la pregunta no está bien. Eso me ha llevado a entenderlo de otra forma
y cuando se pierde la conexión o lo que fuera. i no debería de valer 0?
 
Lo volví a cambiar, jo, lo siento jaja... esta vez comenté lo de //se abre buffer y se empiezan a recibir datos
i vale 0
Si.
Pero hay momentos en los que se están 5 minutos sin recibir llamadas, por lo que en esos 5 minutos i siempre vale 0, de esta manera evito que consuma memoria de los ordenadores al evitar los if y demás.
 
vale, y si simplemente, después del while ((i = stream.Read(bytes, 0, bytes.Length)) != 0). Reinstancias el TCPClient?
Es decir, una vez que has dejado de recibir datos es cuando vuelves a empezar
 
Por que los datos se reciben de manera asíncrona
Entonces, tendría el problema de registros duplicados con valor 0
 
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
//Tu código entero
}
cliente = new TcpClient(); //Reinstanciamos el socket
Si, pero en algún momento para
Que es el problema que estás teniendo
Pues si para, reinicio la conexión
 
4:43 PM
En algún momento para... pero el while (true) sigue por encima
 
correcto, pero ese no me molesta
 
De hecho
 
Te lo pongo entero:
public static void hilo(){
byte[] bytes = new Byte[256];
String data = null;
TcpClient cliente = new TcpClient();
while (true)
{
NetworkStream stream = cliente.GetStream();
int i;

while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Recibido: {0}", data);

data = data.ToUpper();

byte[] msg;

if (data.Contains("login")){

console.write("login username password");
//Se abre buffer de datos y empiezo a recibir datos
En el momento en que se deja de recibir datos. (i == 0), creamos un socket nuevo y volvemos a empezar. Mientras que el socket esté correcto y respondiendo a nuestras peticiones no lo reiniciamos
 
Uhm... el problema sería de nuevo la redundancia. es decir, imáginate yo recibo ahora mismo el valor 5, si reinstancio el tcp, tendría que volver a hacer login, por lo que tendría que volver a hacer queueinfo, por lo que me devuelve un valor 0 y el próximo valor, o el valor real podría ser, 3, 4, 7... depende de la cantidad de llamadas que hubiera en espera. (Son llamadas telefónicas)
 
espera un momento.... me estas diciendo que la respuesta del servidor tarda en llegar hasta 5 minutos y que por eso se recibe i == 0 durante mucho tiempo hasta que llegue respuesta para esa sesión de telnet?
 
4:47 PM
No, la respuesta del servidor es instantanea
Pero entre que entre una llamada y otra pueden perfectamente pasar o 2 segundos o 5 minutos o 2 horas.
Por lo que los datos se reciben cada 2 segundos o 5 minutos o ...
No es constante.
 
Pero y eso que más da? Stream.Read devuelve el número de bytes leidos. Si no se ha recibido ningún byte. No hay información que recibir. No es que la información devuelta sea que haya 0 llamadas en cola
Los datos de respuesta están en "bytes" no en la "i"
O te he entendido mal?
 
Los datos recibiidos en efecto están en bytes
pero bytes no recibe datos constantemente.
 
Vale, pues cuando no reciba, inicio el socket de nuevo. Con su login y todo.
Estoy viendo esa solución tan obvia y tu lo estás viendo tan poco obvia que me da que no nos estamos entendiendo mutuamente correctamente jeje
Seguramente me falta información
 
Lo veo obvio, y coherente incluso, pero no como una solución válida, ya que, lo que yo quiero es que únicamente reinicie el socket cuando no haya datos, y como te digo el socket únicamente me da información cuando llega una nueva llamada, la mayoría del tiempo no recibe nada.
de hecho, probé a enviar toda la información que este recibía en stream a un txt la primera vez cuando me puse con el programa, y como te digo, la información que recibía era cada X tiempo, no era algo constante, muchas veces no había nada en 5 minutos, por lo que ... volvemos a lo que te he dicho antes.
Es como... si abriera un puerto, y de vez en cuando este me dijera, oye, que hay una llamada, oye, que ahora hay dos, y ahora otra vez una, otra vez dos, y ahora tres...
De forma de que no es constante. :(
De todas formas creo que voy a dar esto por zanjado, hablaré con mi jefe cuando pueda y veremos como enfocamos el proyecto, a ver si alguien con algo más de experiencia que yo puede hacerse cargo o echarme una mano, o ver si podemos hacer que el programa inicie cada hora.
Si eso, responde a la pregunta con la típica imagen de el ciclo de vida de los procesos y te la doy como válida por todo el tiempo que has dedicado a ello, así al menos te llevas la reputación.
Tengo que dejar ya esto y volver a mi casa, muchas gracias por todo.
 
5:12 PM
No te preocupes Aritz! Seguimos la conversación mañana. La reputación me preocupa bien poco, me gusta que las preguntas tengan respuesta y se fijen como tal haya respondido yo o cualquiera. No obstante, este problema me intriga y creo que le podemos dar una solución.
Para cuando puedas leerlo: Entiendo que el problema que ves es no saturar el servidor con un nuevo inicio de sesión cada vez que esté sin recibir datos. Entiendo esa preocupación. Si no podemos tener un indicador de cuando preguntar por la información, ni de cuando la conexión se encuentra inoperable, no podemos reaccionar a eventos controlables para poder resolver el problema debidamente.
no obstante, lo que si que podemos hacer es establecer unos "Ticks" o periodos de vida para cada lectura. Es decir, definir una vida máxima para el socket (sabiendo que nos da problemas si se queda mucho tiempo abierto) y reinciar la comunicación cada ese X. No es la solución más elegante, pero podría solucionar el problema. coméntame como verías esa solución.
 

last day (15 days later) »