hilos en C# y pda

07/04/2008 - 08:57 por Aitziber | Informe spam
Hola necesito saber como utilizar hilos en una aplicacion de winform para
pda.
Tengo una funcion que escribe en unos label... y quiero que esa funcion sea
un hilo y luego todo el programa que sea el hilo principal.

Como puedo hacerlo??

Preguntas similare

Leer las respuestas

#6 Aitziber
08/04/2008 - 16:18 | Informe spam
Bien, yo lo hago asi pero no me funciona correctamente.

Mi problema es que yo tengo un evento de recibir datos por linea serie.
Necesito hacer un hilo para ir mostrando por pantalla de la PDA (en unos
labels) y a su vez seguir recibiendo datos en el evento citado via linea
serie.

Si quieres te pongo el codigo que he hecho como ejemplo

"RFOG" escribió en el mensaje
news:
A ver, tu has dicho que quieres actualizar la UI desde un hilo, no cómo
hacer un hilo. Yo te he explicado cómo actualizar la UI desde un hilo, es
decir, desde ese hilo debes llamar a mi AddLog() y todo funcionará
perfectamente.

Ahora bien, si lo que quieres es saber cómo crear un hilo, eso es otra
cosa, y tienes muchas opciones, desde crearlo a mano, mediante el
componente Process o un ThreadPool... y algunas más seguro.

La forma más sencilla de crear un hilo es:

Declarar una variable de tipo Thread:

Thread miHilo;

Definir un método que va a ser el hilo en ejecución:

void Hilo(void)
{
while(!terminar)
{
//Hacer cosas
}
}

Y luego asignarlo donde quieras crearlo:

miThread=new Thread(Hilo);

Hay muchas otras formas de crear un hilo, pero esta es la más sencilla.

Luego, cuando llames a

miThread.Start();

el hilo se lanzará, es decir, se ejecutará el método Hilo() hasta que
termine él solo o tu lo mantes.

Si haces

miThread.IsBackground=true;

el hilo se debe terminar solo cuando cierres la aplicación... aunque a
veces, si está enganchado en un objeto del núcleo (por ejemplo, un puerto
serie) no se termina, o al menos a mi a veces no se me ha terminado, así
que para cosas más o menos triviales, yo uso esto:
http://geeks.ms/blogs/rfog/archive/...ilos.aspx.
Aunque esté en C++/CLI el concepto se entiende, y si quieres comprobar el
código en C#, quita los "tejaícos" y cambia -> por . y :: por . y debería
compilarte en C#.


"Aitziber" escribió en el mensaje de noticias
news:
Pero de esta manera donde creas el hilo???
Thread mi_hilo.





"RFOG" escribió en el mensaje
news:
A ver. Si tienes un hilo, desde ese hilo no puedes acceder a los
controles de la ficha. En versiones anteriores a la 2.0, funcionaba hasta
que funcionaba y todo petaba. A partir de la 2.0 se genera una excepción
que te lo dice.

Para evitarlo, las fichas tienen un método que se llama Invoke
(http://msdn2.microsoft.com/es-es/li...hdc6b.aspx) y que ejecuta
un delegado en el hilo propietario de los controles (en general el hilo
principal). Entonces, para actualizar la UI necesitas crearte un
delegado y llamarlo con el Invoke de la ficha desde tu hilo.

Si no sabes qué es un delegado, aquí lo tienes explicado:
http://msdn2.microsoft.com/es-es/li...sk6y.aspx.

Por lo tanto, el código de abajo declara un delegado que recibe una
cadena

private delegate void AddLogDelegate(string s);





Y luego clara una variable que va a contener el delegado

private AddLogDelegate m_addLog;





También declara un método que define el funcionamiento del delegado:

private void AddLogReal(string s)
{
m_lbLog.Items.Add(s);
m_lbLog.SelectedIndex = m_lbLog.Items.Count - 1;
}





En este caso, añade a un listbox la cadena pasada y coloca la selección
en esa misma cadena. En tu programa, pues cambiará los valores del
label.

Luego en el constructor de la ficha, asigna el delegado:

m_addLog=new AddLogDelegate(AddLogReal);





También crea otro método que será llamado por el hilo:

private void AddLog(string s)
{
Invoke(m_addLog, new string[] { s });
}





Luego, dentro del hilo en cuestión, se llama a

AddLog("Hola Mundo");

que a su vez llamará al método AddLogReal a través del Inoke de la
ficha, actualizando los controles pertinentes.

Tu te puedes ahorrar implementar el método AddLog y colocando su
contenido dentro del hilo cuando quieras actualizar esa parte de la UI:

//tu hilo
this->Invoke(m_addLog, new string[] { "HOLA MUNDO" });

Y ya está.


"Aitziber" wrote in message
news:
NO entiendo muy bien como tengo que hacerlo.
Me lo podrias explicar un poco mas

"RFOG" escribió en el mensaje
news:
Hola.

No puedes actualizar directamente los label desde un hilo que no sea
el principal. Lo que tienes que hacer es llamar mediante el método
Invoke del form a un delegado que te hayas creado y que sea el que
actualice los label.

private delegate void AddLogDelegate(string s);
private AddLogDelegate m_addLog;
private void AddLog(string s)
{
Invoke(m_addLog, new string[] { s });
}
private void AddLogReal(string s)
{
m_lbLog.Items.Add(s);
m_lbLog.SelectedIndex = m_lbLog.Items.Count - 1;
}

El método AddLog() es llamado desde el hilo, que a su vez llama
mediante un Invoke a AddLogReal que es el que realmente hace el
trabajo.

el delegado m_addLog lo inicializo en el constructor de la ficha:

m_addLog=new AddLogDelegate(AddLogReal);

Así me evito estar asignando/borrando delegados todo el tiempo.

Depende de qué hagas, quizás te sea más interesante hacer la llamada
directamente desde el hilo en lugar de utilizar el método AddLog...

"Aitziber" wrote in message
news:
Hola necesito saber como utilizar hilos en una aplicacion de winform
para pda.
Tengo una funcion que escribe en unos label... y quiero que esa
funcion sea un hilo y luego todo el programa que sea el hilo
principal.

Como puedo hacerlo??




Microsoft Visual C++ MVP
==>>>>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
>>>>> Buena cosa es tener amigos, pero mala el tener necesidad de ellos.








Microsoft Visual C++ MVP
==>>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
>>> Buena cosa es tener amigos, pero mala el tener necesidad de ellos.








Microsoft Visual C++ MVP
==> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
> Flores pintadas, no huelen a nada.

Respuesta Responder a este mensaje
#7 RFOG
08/04/2008 - 17:28 | Informe spam
Entonces el problema que tienes es que no te da tiempo a recibir los datos y
a actualizarlos en el mismo hilo, ¿no? Es decir, tienes un hilo que hace una
lectura del puerto serie y cuando tiene algo válido llama al método que
actualiza la función, y no te da tiempo a hacerlo.

Si es así, lo único que se me ocurre es que tengas dos hilos, uno para
recibir por el puerto serie y que coloque lo recibido en una cola, y otro
que vaya leyendo la cola y la vaya sacando por pantalla (y entonces la cola
irá creciendo y tendrás que decidir cuándo vaciarla e ignorar ciertos
mensajes)... pero pon el código del hilo, a ver si estuvieras haciendo algo
mal.

"Aitziber" escribió en el mensaje de noticias
news:O%
Bien, yo lo hago asi pero no me funciona correctamente.

Mi problema es que yo tengo un evento de recibir datos por linea serie.
Necesito hacer un hilo para ir mostrando por pantalla de la PDA (en unos
labels) y a su vez seguir recibiendo datos en el evento citado via linea
serie.

Si quieres te pongo el codigo que he hecho como ejemplo

"RFOG" escribió en el mensaje
news:
A ver, tu has dicho que quieres actualizar la UI desde un hilo, no cómo
hacer un hilo. Yo te he explicado cómo actualizar la UI desde un hilo, es
decir, desde ese hilo debes llamar a mi AddLog() y todo funcionará
perfectamente.

Ahora bien, si lo que quieres es saber cómo crear un hilo, eso es otra
cosa, y tienes muchas opciones, desde crearlo a mano, mediante el
componente Process o un ThreadPool... y algunas más seguro.

La forma más sencilla de crear un hilo es:

Declarar una variable de tipo Thread:

Thread miHilo;

Definir un método que va a ser el hilo en ejecución:

void Hilo(void)
{
while(!terminar)
{
//Hacer cosas
}
}

Y luego asignarlo donde quieras crearlo:

miThread=new Thread(Hilo);

Hay muchas otras formas de crear un hilo, pero esta es la más sencilla.

Luego, cuando llames a

miThread.Start();

el hilo se lanzará, es decir, se ejecutará el método Hilo() hasta que
termine él solo o tu lo mantes.

Si haces

miThread.IsBackground=true;

el hilo se debe terminar solo cuando cierres la aplicación... aunque a
veces, si está enganchado en un objeto del núcleo (por ejemplo, un puerto
serie) no se termina, o al menos a mi a veces no se me ha terminado, así
que para cosas más o menos triviales, yo uso esto:
http://geeks.ms/blogs/rfog/archive/...ilos.aspx.
Aunque esté en C++/CLI el concepto se entiende, y si quieres comprobar el
código en C#, quita los "tejaícos" y cambia -> por . y :: por . y debería
compilarte en C#.


"Aitziber" escribió en el mensaje de noticias
news:
Pero de esta manera donde creas el hilo???
Thread mi_hilo.





"RFOG" escribió en el mensaje
news:
A ver. Si tienes un hilo, desde ese hilo no puedes acceder a los
controles de la ficha. En versiones anteriores a la 2.0, funcionaba
hasta que funcionaba y todo petaba. A partir de la 2.0 se genera una
excepción que te lo dice.

Para evitarlo, las fichas tienen un método que se llama Invoke
(http://msdn2.microsoft.com/es-es/li...hdc6b.aspx) y que ejecuta
un delegado en el hilo propietario de los controles (en general el hilo
principal). Entonces, para actualizar la UI necesitas crearte un
delegado y llamarlo con el Invoke de la ficha desde tu hilo.

Si no sabes qué es un delegado, aquí lo tienes explicado:
http://msdn2.microsoft.com/es-es/li...sk6y.aspx.

Por lo tanto, el código de abajo declara un delegado que recibe una
cadena

private delegate void AddLogDelegate(string s);





Y luego clara una variable que va a contener el delegado

private AddLogDelegate m_addLog;





También declara un método que define el funcionamiento del delegado:

private void AddLogReal(string s)
{
m_lbLog.Items.Add(s);
m_lbLog.SelectedIndex = m_lbLog.Items.Count - 1;
}





En este caso, añade a un listbox la cadena pasada y coloca la selección
en esa misma cadena. En tu programa, pues cambiará los valores del
label.

Luego en el constructor de la ficha, asigna el delegado:

m_addLog=new AddLogDelegate(AddLogReal);





También crea otro método que será llamado por el hilo:

private void AddLog(string s)
{
Invoke(m_addLog, new string[] { s });
}





Luego, dentro del hilo en cuestión, se llama a

AddLog("Hola Mundo");

que a su vez llamará al método AddLogReal a través del Inoke de la
ficha, actualizando los controles pertinentes.

Tu te puedes ahorrar implementar el método AddLog y colocando su
contenido dentro del hilo cuando quieras actualizar esa parte de la UI:

//tu hilo
this->Invoke(m_addLog, new string[] { "HOLA MUNDO" });

Y ya está.


"Aitziber" wrote in message
news:
NO entiendo muy bien como tengo que hacerlo.
Me lo podrias explicar un poco mas

"RFOG" escribió en el mensaje
news:
Hola.

No puedes actualizar directamente los label desde un hilo que no sea
el principal. Lo que tienes que hacer es llamar mediante el método
Invoke del form a un delegado que te hayas creado y que sea el que
actualice los label.

private delegate void AddLogDelegate(string s);
private AddLogDelegate m_addLog;
private void AddLog(string s)
{
Invoke(m_addLog, new string[] { s });
}
private void AddLogReal(string s)
{
m_lbLog.Items.Add(s);
m_lbLog.SelectedIndex = m_lbLog.Items.Count - 1;
}

El método AddLog() es llamado desde el hilo, que a su vez llama
mediante un Invoke a AddLogReal que es el que realmente hace el
trabajo.

el delegado m_addLog lo inicializo en el constructor de la ficha:

m_addLog=new AddLogDelegate(AddLogReal);

Así me evito estar asignando/borrando delegados todo el tiempo.

Depende de qué hagas, quizás te sea más interesante hacer la llamada
directamente desde el hilo en lugar de utilizar el método AddLog...

"Aitziber" wrote in message
news:
Hola necesito saber como utilizar hilos en una aplicacion de winform
para pda.
Tengo una funcion que escribe en unos label... y quiero que esa
funcion sea un hilo y luego todo el programa que sea el hilo
principal.

Como puedo hacerlo??




Microsoft Visual C++ MVP
==>>>>>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
>>>>>> Buena cosa es tener amigos, pero mala el tener necesidad de ellos.








Microsoft Visual C++ MVP
==>>>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
>>>> Buena cosa es tener amigos, pero mala el tener necesidad de ellos.








Microsoft Visual C++ MVP
==>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
>> Flores pintadas, no huelen a nada.








Microsoft Visual C++ MVP
==Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
Flores pintadas, no huelen a nada.
Respuesta Responder a este mensaje
#8 Aitziber
09/04/2008 - 08:47 | Informe spam
Este es mi codigo. bueno una prueba inicial que estoy hacien para luego
hacerlo en mi aplicacion.
namespace Prueba_Hilos

{

public partial class Hilos : Form

{

string[] velocidad = new string[] { "4800", "9600", "19200" };

string[] puertos = new string[] { "COM1", "COM3", "COM4", "COM5", "COM7" };

private delegate void mi_hilo();

mi_hilo hilo;

Thread t;

int kont = 0;

bool recibido = false;

bool terminar;

public Hilos()

{

InitializeComponent();

//mostrar velocidades posibles de comunicacion

foreach (string baudio in velocidad)

{

Bps.Items.Add(baudio);

}

foreach (string puert in puertos)

{

puerto.Items.Add(puert);

}

t = new Thread(new ThreadStart(ThreadProc));

hilo = new mi_hilo(funcion_hilo);

}

private void Cerrar_Click(object sender, EventArgs e)

{

terminar = true;

if (port.IsOpen)

port.Close();

}

private void Abrir_Click(object sender, EventArgs e)

{

if (port.IsOpen)

port.Close();

//guardar el valor de los baudios. Por defecto será 4800

if (Bps.Text != "")

{

port.BaudRate = Convert.ToInt32(Bps.Text);

}

//guardar el nombre del puerto que queremos abrir que por defecto será COM4

if (puerto.Text != "")

{

port.PortName = puerto.Text;

}

//abrir el puerto

port.Open();

t.Start();

terminar = false;

}

private void port_DataReceived(object sender,
System.IO.Ports.SerialDataReceivedEventArgs e)

{

//Invoke(principal);

//this.Invoke(new EventHandler(principal));

principal();

}

//private void principal(object s, EventArgs e)

private void principal()

{

//t.Start();

recibido = true;

}

private void ThreadProc()

{

Invoke(hilo);

}

private void funcion_hilo()

{

while (!terminar)

{

if (recibido == true)

{

kont++;

contador.Text = kont.ToString();

recibido = false;

}

}

}

}

}



"RFOG" escribió en el mensaje
news:
Entonces el problema que tienes es que no te da tiempo a recibir los datos
y a actualizarlos en el mismo hilo, ¿no? Es decir, tienes un hilo que hace
una lectura del puerto serie y cuando tiene algo válido llama al método
que actualiza la función, y no te da tiempo a hacerlo.

Si es así, lo único que se me ocurre es que tengas dos hilos, uno para
recibir por el puerto serie y que coloque lo recibido en una cola, y otro
que vaya leyendo la cola y la vaya sacando por pantalla (y entonces la
cola irá creciendo y tendrás que decidir cuándo vaciarla e ignorar ciertos
mensajes)... pero pon el código del hilo, a ver si estuvieras haciendo
algo mal.

"Aitziber" escribió en el mensaje de noticias
news:O%
Bien, yo lo hago asi pero no me funciona correctamente.

Mi problema es que yo tengo un evento de recibir datos por linea serie.
Necesito hacer un hilo para ir mostrando por pantalla de la PDA (en unos
labels) y a su vez seguir recibiendo datos en el evento citado via linea
serie.

Si quieres te pongo el codigo que he hecho como ejemplo

"RFOG" escribió en el mensaje
news:
A ver, tu has dicho que quieres actualizar la UI desde un hilo, no cómo
hacer un hilo. Yo te he explicado cómo actualizar la UI desde un hilo, es
decir, desde ese hilo debes llamar a mi AddLog() y todo funcionará
perfectamente.

Ahora bien, si lo que quieres es saber cómo crear un hilo, eso es otra
cosa, y tienes muchas opciones, desde crearlo a mano, mediante el
componente Process o un ThreadPool... y algunas más seguro.

La forma más sencilla de crear un hilo es:

Declarar una variable de tipo Thread:

Thread miHilo;

Definir un método que va a ser el hilo en ejecución:

void Hilo(void)
{
while(!terminar)
{
//Hacer cosas
}
}

Y luego asignarlo donde quieras crearlo:

miThread=new Thread(Hilo);

Hay muchas otras formas de crear un hilo, pero esta es la más sencilla.

Luego, cuando llames a

miThread.Start();

el hilo se lanzará, es decir, se ejecutará el método Hilo() hasta que
termine él solo o tu lo mantes.

Si haces

miThread.IsBackground=true;

el hilo se debe terminar solo cuando cierres la aplicación... aunque a
veces, si está enganchado en un objeto del núcleo (por ejemplo, un
puerto serie) no se termina, o al menos a mi a veces no se me ha
terminado, así que para cosas más o menos triviales, yo uso esto:
http://geeks.ms/blogs/rfog/archive/...ilos.aspx.
Aunque esté en C++/CLI el concepto se entiende, y si quieres comprobar
el código en C#, quita los "tejaícos" y cambia -> por . y :: por . y
debería compilarte en C#.


"Aitziber" escribió en el mensaje de noticias
news:
Pero de esta manera donde creas el hilo???
Thread mi_hilo.





"RFOG" escribió en el mensaje
news:
A ver. Si tienes un hilo, desde ese hilo no puedes acceder a los
controles de la ficha. En versiones anteriores a la 2.0, funcionaba
hasta que funcionaba y todo petaba. A partir de la 2.0 se genera una
excepción que te lo dice.

Para evitarlo, las fichas tienen un método que se llama Invoke
(http://msdn2.microsoft.com/es-es/li...hdc6b.aspx) y que ejecuta
un delegado en el hilo propietario de los controles (en general el
hilo principal). Entonces, para actualizar la UI necesitas crearte un
delegado y llamarlo con el Invoke de la ficha desde tu hilo.

Si no sabes qué es un delegado, aquí lo tienes explicado:
http://msdn2.microsoft.com/es-es/li...sk6y.aspx.

Por lo tanto, el código de abajo declara un delegado que recibe una
cadena

private delegate void AddLogDelegate(string s);





Y luego clara una variable que va a contener el delegado

private AddLogDelegate m_addLog;





También declara un método que define el funcionamiento del delegado:

private void AddLogReal(string s)
{
m_lbLog.Items.Add(s);
m_lbLog.SelectedIndex = m_lbLog.Items.Count - 1;
}





En este caso, añade a un listbox la cadena pasada y coloca la
selección en esa misma cadena. En tu programa, pues cambiará los
valores del label.

Luego en el constructor de la ficha, asigna el delegado:

m_addLog=new AddLogDelegate(AddLogReal);





También crea otro método que será llamado por el hilo:

private void AddLog(string s)
{
Invoke(m_addLog, new string[] { s });
}





Luego, dentro del hilo en cuestión, se llama a

AddLog("Hola Mundo");

que a su vez llamará al método AddLogReal a través del Inoke de la
ficha, actualizando los controles pertinentes.

Tu te puedes ahorrar implementar el método AddLog y colocando su
contenido dentro del hilo cuando quieras actualizar esa parte de la
UI:

//tu hilo
this->Invoke(m_addLog, new string[] { "HOLA MUNDO" });

Y ya está.


"Aitziber" wrote in message
news:
NO entiendo muy bien como tengo que hacerlo.
Me lo podrias explicar un poco mas

"RFOG" escribió en el mensaje
news:
Hola.

No puedes actualizar directamente los label desde un hilo que no sea
el principal. Lo que tienes que hacer es llamar mediante el método
Invoke del form a un delegado que te hayas creado y que sea el que
actualice los label.

private delegate void AddLogDelegate(string s);
private AddLogDelegate m_addLog;
private void AddLog(string s)
{
Invoke(m_addLog, new string[] { s });
}
private void AddLogReal(string s)
{
m_lbLog.Items.Add(s);
m_lbLog.SelectedIndex = m_lbLog.Items.Count - 1;
}

El método AddLog() es llamado desde el hilo, que a su vez llama
mediante un Invoke a AddLogReal que es el que realmente hace el
trabajo.

el delegado m_addLog lo inicializo en el constructor de la ficha:

m_addLog=new AddLogDelegate(AddLogReal);

Así me evito estar asignando/borrando delegados todo el tiempo.

Depende de qué hagas, quizás te sea más interesante hacer la llamada
directamente desde el hilo en lugar de utilizar el método AddLog...

"Aitziber" wrote in message
news:
Hola necesito saber como utilizar hilos en una aplicacion de
winform para pda.
Tengo una funcion que escribe en unos label... y quiero que esa
funcion sea un hilo y luego todo el programa que sea el hilo
principal.

Como puedo hacerlo??




Microsoft Visual C++ MVP
==>>>>>>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
>>>>>>> Buena cosa es tener amigos, pero mala el tener necesidad de ellos.








Microsoft Visual C++ MVP
==>>>>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
>>>>> Buena cosa es tener amigos, pero mala el tener necesidad de ellos.








Microsoft Visual C++ MVP
==>>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
>>> Flores pintadas, no huelen a nada.








Microsoft Visual C++ MVP
==> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
> Flores pintadas, no huelen a nada.

Respuesta Responder a este mensaje
#9 RFOG
10/04/2008 - 13:17 | Informe spam
Buff, qué lio.

En el evento DataReceived no necesitas para nada llamar a principal(),
simplemente pon recibido a true, y haz recibido volatile porque si no no va
a funcionar (lee el por qué en mi entrada del blog que te puse)...

Luego tienes un hilo que está durmiendo y que cuando hay algo en el puerto
serie, despierta y hace algo (pero lo tienes mal porque ese hilo no lo
duermes y seguro que le subes a la PDA la CPU al 100%), y luego tienes otro
hilo más que hace un invoque que no tiene nada que ver con nada, que también
te sube la CPU al 100%...

De un plumazo: en el evento DataReceived del Puerto Serie haz un Invoke a un
delegado que actualice el label. Todo lo demás sobra.

Algo así:

private void port_DataReceived(object sender,
System.IO.Ports.SerialDataReceivedEventArgs e)
{
Invoke(ActualizaContador);
}
delegate void ActualizaContadorDelegate(void);
void ActualizaContador()
{
kont++;
label.Text=kont.ToString();
}

Si quieres no estar creando un delegado cada vez, hazlo así:

private void port_DataReceived(object sender,
System.IO.Ports.SerialDataReceivedEventArgs e)
{
Invoke(m_actualizaContador);
}
delegate void ActualizaContadorDelegate(void);
ActualizaContador m_actualizaContador;
void ActualizaContador()
{
kont++;
label.Text=kont.ToString();
}

Y en el constructor de la clase,

m_actualizaContador=new ActualizaContadorDelegate(ActualizaContador);

"Aitziber" escribió en el mensaje de noticias
news:%
Este es mi codigo. bueno una prueba inicial que estoy hacien para luego
hacerlo en mi aplicacion.
namespace Prueba_Hilos

{

public partial class Hilos : Form

{

string[] velocidad = new string[] { "4800", "9600", "19200" };

string[] puertos = new string[] { "COM1", "COM3", "COM4", "COM5",
"COM7" };

private delegate void mi_hilo();

mi_hilo hilo;

Thread t;

int kont = 0;

bool recibido = false;

bool terminar;

public Hilos()

{

InitializeComponent();

//mostrar velocidades posibles de comunicacion

foreach (string baudio in velocidad)

{

Bps.Items.Add(baudio);

}

foreach (string puert in puertos)

{

puerto.Items.Add(puert);

}

t = new Thread(new ThreadStart(ThreadProc));

hilo = new mi_hilo(funcion_hilo);

}

private void Cerrar_Click(object sender, EventArgs e)

{

terminar = true;

if (port.IsOpen)

port.Close();

}

private void Abrir_Click(object sender, EventArgs e)

{

if (port.IsOpen)

port.Close();

//guardar el valor de los baudios. Por defecto será 4800

if (Bps.Text != "")

{

port.BaudRate = Convert.ToInt32(Bps.Text);

}

//guardar el nombre del puerto que queremos abrir que por defecto será
COM4

if (puerto.Text != "")

{

port.PortName = puerto.Text;

}

//abrir el puerto

port.Open();

t.Start();

terminar = false;

}

private void port_DataReceived(object sender,
System.IO.Ports.SerialDataReceivedEventArgs e)

{

//Invoke(principal);

//this.Invoke(new EventHandler(principal));

principal();

}

//private void principal(object s, EventArgs e)

private void principal()

{

//t.Start();

recibido = true;

}

private void ThreadProc()

{

Invoke(hilo);

}

private void funcion_hilo()

{

while (!terminar)

{

if (recibido == true)

{

kont++;

contador.Text = kont.ToString();

recibido = false;

}

}

}

}

}



"RFOG" escribió en el mensaje
news:
Entonces el problema que tienes es que no te da tiempo a recibir los
datos y a actualizarlos en el mismo hilo, ¿no? Es decir, tienes un hilo
que hace una lectura del puerto serie y cuando tiene algo válido llama al
método que actualiza la función, y no te da tiempo a hacerlo.

Si es así, lo único que se me ocurre es que tengas dos hilos, uno para
recibir por el puerto serie y que coloque lo recibido en una cola, y otro
que vaya leyendo la cola y la vaya sacando por pantalla (y entonces la
cola irá creciendo y tendrás que decidir cuándo vaciarla e ignorar
ciertos mensajes)... pero pon el código del hilo, a ver si estuvieras
haciendo algo mal.

"Aitziber" escribió en el mensaje de noticias
news:O%
Bien, yo lo hago asi pero no me funciona correctamente.

Mi problema es que yo tengo un evento de recibir datos por linea serie.
Necesito hacer un hilo para ir mostrando por pantalla de la PDA (en unos
labels) y a su vez seguir recibiendo datos en el evento citado via linea
serie.

Si quieres te pongo el codigo que he hecho como ejemplo

"RFOG" escribió en el mensaje
news:
A ver, tu has dicho que quieres actualizar la UI desde un hilo, no cómo
hacer un hilo. Yo te he explicado cómo actualizar la UI desde un hilo,
es decir, desde ese hilo debes llamar a mi AddLog() y todo funcionará
perfectamente.

Ahora bien, si lo que quieres es saber cómo crear un hilo, eso es otra
cosa, y tienes muchas opciones, desde crearlo a mano, mediante el
componente Process o un ThreadPool... y algunas más seguro.

La forma más sencilla de crear un hilo es:

Declarar una variable de tipo Thread:

Thread miHilo;

Definir un método que va a ser el hilo en ejecución:

void Hilo(void)
{
while(!terminar)
{
//Hacer cosas
}
}

Y luego asignarlo donde quieras crearlo:

miThread=new Thread(Hilo);

Hay muchas otras formas de crear un hilo, pero esta es la más sencilla.

Luego, cuando llames a

miThread.Start();

el hilo se lanzará, es decir, se ejecutará el método Hilo() hasta que
termine él solo o tu lo mantes.

Si haces

miThread.IsBackground=true;

el hilo se debe terminar solo cuando cierres la aplicación... aunque a
veces, si está enganchado en un objeto del núcleo (por ejemplo, un
puerto serie) no se termina, o al menos a mi a veces no se me ha
terminado, así que para cosas más o menos triviales, yo uso esto:
http://geeks.ms/blogs/rfog/archive/...ilos.aspx.
Aunque esté en C++/CLI el concepto se entiende, y si quieres comprobar
el código en C#, quita los "tejaícos" y cambia -> por . y :: por . y
debería compilarte en C#.


"Aitziber" escribió en el mensaje de noticias
news:
Pero de esta manera donde creas el hilo???
Thread mi_hilo.





"RFOG" escribió en el mensaje
news:
A ver. Si tienes un hilo, desde ese hilo no puedes acceder a los
controles de la ficha. En versiones anteriores a la 2.0, funcionaba
hasta que funcionaba y todo petaba. A partir de la 2.0 se genera una
excepción que te lo dice.

Para evitarlo, las fichas tienen un método que se llama Invoke
(http://msdn2.microsoft.com/es-es/li...hdc6b.aspx) y que
ejecuta un delegado en el hilo propietario de los controles (en
general el hilo principal). Entonces, para actualizar la UI necesitas
crearte un delegado y llamarlo con el Invoke de la ficha desde tu
hilo.

Si no sabes qué es un delegado, aquí lo tienes explicado:
http://msdn2.microsoft.com/es-es/li...sk6y.aspx.

Por lo tanto, el código de abajo declara un delegado que recibe una
cadena

private delegate void AddLogDelegate(string s);





Y luego clara una variable que va a contener el delegado

private AddLogDelegate m_addLog;





También declara un método que define el funcionamiento del delegado:

private void AddLogReal(string s)
{
m_lbLog.Items.Add(s);
m_lbLog.SelectedIndex = m_lbLog.Items.Count - 1;
}





En este caso, añade a un listbox la cadena pasada y coloca la
selección en esa misma cadena. En tu programa, pues cambiará los
valores del label.

Luego en el constructor de la ficha, asigna el delegado:

m_addLog=new AddLogDelegate(AddLogReal);





También crea otro método que será llamado por el hilo:

private void AddLog(string s)
{
Invoke(m_addLog, new string[] { s });
}





Luego, dentro del hilo en cuestión, se llama a

AddLog("Hola Mundo");

que a su vez llamará al método AddLogReal a través del Inoke de la
ficha, actualizando los controles pertinentes.

Tu te puedes ahorrar implementar el método AddLog y colocando su
contenido dentro del hilo cuando quieras actualizar esa parte de la
UI:

//tu hilo
this->Invoke(m_addLog, new string[] { "HOLA MUNDO" });

Y ya está.


"Aitziber" wrote in message
news:
NO entiendo muy bien como tengo que hacerlo.
Me lo podrias explicar un poco mas

"RFOG" escribió en el mensaje
news:
Hola.

No puedes actualizar directamente los label desde un hilo que no
sea el principal. Lo que tienes que hacer es llamar mediante el
método Invoke del form a un delegado que te hayas creado y que sea
el que actualice los label.

private delegate void AddLogDelegate(string s);
private AddLogDelegate m_addLog;
private void AddLog(string s)
{
Invoke(m_addLog, new string[] { s });
}
private void AddLogReal(string s)
{
m_lbLog.Items.Add(s);
m_lbLog.SelectedIndex = m_lbLog.Items.Count - 1;
}

El método AddLog() es llamado desde el hilo, que a su vez llama
mediante un Invoke a AddLogReal que es el que realmente hace el
trabajo.

el delegado m_addLog lo inicializo en el constructor de la ficha:

m_addLog=new AddLogDelegate(AddLogReal);

Así me evito estar asignando/borrando delegados todo el tiempo.

Depende de qué hagas, quizás te sea más interesante hacer la
llamada directamente desde el hilo en lugar de utilizar el método
AddLog...

"Aitziber" wrote in message
news:
Hola necesito saber como utilizar hilos en una aplicacion de
winform para pda.
Tengo una funcion que escribe en unos label... y quiero que esa
funcion sea un hilo y luego todo el programa que sea el hilo
principal.

Como puedo hacerlo??




Microsoft Visual C++ MVP
==>>>>>>>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
>>>>>>>> Buena cosa es tener amigos, pero mala el tener necesidad de ellos.








Microsoft Visual C++ MVP
==>>>>>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
>>>>>> Buena cosa es tener amigos, pero mala el tener necesidad de ellos.








Microsoft Visual C++ MVP
==>>>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
>>>> Flores pintadas, no huelen a nada.








Microsoft Visual C++ MVP
==>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
>> Flores pintadas, no huelen a nada.








Microsoft Visual C++ MVP
==Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
La fuerza es el derecho de las bestias.
Respuesta Responder a este mensaje
#10 Aitziber
10/04/2008 - 15:13 | Informe spam
En mi programa inicial, que este no es el codigo lo tengo hecho asi. Pero de
esta manera si esta en la funcion que llame el Invoke a la vez se ejecutara
el data received???
No se si me explico
"RFOG" escribió en el mensaje
news:
Buff, qué lio.

En el evento DataReceived no necesitas para nada llamar a principal(),
simplemente pon recibido a true, y haz recibido volatile porque si no no
va a funcionar (lee el por qué en mi entrada del blog que te puse)...

Luego tienes un hilo que está durmiendo y que cuando hay algo en el puerto
serie, despierta y hace algo (pero lo tienes mal porque ese hilo no lo
duermes y seguro que le subes a la PDA la CPU al 100%), y luego tienes
otro hilo más que hace un invoque que no tiene nada que ver con nada, que
también te sube la CPU al 100%...

De un plumazo: en el evento DataReceived del Puerto Serie haz un Invoke a
un delegado que actualice el label. Todo lo demás sobra.

Algo así:

private void port_DataReceived(object sender,
System.IO.Ports.SerialDataReceivedEventArgs e)
{
Invoke(ActualizaContador);
}
delegate void ActualizaContadorDelegate(void);
void ActualizaContador()
{
kont++;
label.Text=kont.ToString();
}

Si quieres no estar creando un delegado cada vez, hazlo así:

private void port_DataReceived(object sender,
System.IO.Ports.SerialDataReceivedEventArgs e)
{
Invoke(m_actualizaContador);
}
delegate void ActualizaContadorDelegate(void);
ActualizaContador m_actualizaContador;
void ActualizaContador()
{
kont++;
label.Text=kont.ToString();
}

Y en el constructor de la clase,

m_actualizaContador=new ActualizaContadorDelegate(ActualizaContador);

"Aitziber" escribió en el mensaje de noticias
news:%
Este es mi codigo. bueno una prueba inicial que estoy hacien para luego
hacerlo en mi aplicacion.
namespace Prueba_Hilos

{

public partial class Hilos : Form

{

string[] velocidad = new string[] { "4800", "9600", "19200" };

string[] puertos = new string[] { "COM1", "COM3", "COM4", "COM5",
"COM7" };

private delegate void mi_hilo();

mi_hilo hilo;

Thread t;

int kont = 0;

bool recibido = false;

bool terminar;

public Hilos()

{

InitializeComponent();

//mostrar velocidades posibles de comunicacion

foreach (string baudio in velocidad)

{

Bps.Items.Add(baudio);

}

foreach (string puert in puertos)

{

puerto.Items.Add(puert);

}

t = new Thread(new ThreadStart(ThreadProc));

hilo = new mi_hilo(funcion_hilo);

}

private void Cerrar_Click(object sender, EventArgs e)

{

terminar = true;

if (port.IsOpen)

port.Close();

}

private void Abrir_Click(object sender, EventArgs e)

{

if (port.IsOpen)

port.Close();

//guardar el valor de los baudios. Por defecto será 4800

if (Bps.Text != "")

{

port.BaudRate = Convert.ToInt32(Bps.Text);

}

//guardar el nombre del puerto que queremos abrir que por defecto será
COM4

if (puerto.Text != "")

{

port.PortName = puerto.Text;

}

//abrir el puerto

port.Open();

t.Start();

terminar = false;

}

private void port_DataReceived(object sender,
System.IO.Ports.SerialDataReceivedEventArgs e)

{

//Invoke(principal);

//this.Invoke(new EventHandler(principal));

principal();

}

//private void principal(object s, EventArgs e)

private void principal()

{

//t.Start();

recibido = true;

}

private void ThreadProc()

{

Invoke(hilo);

}

private void funcion_hilo()

{

while (!terminar)

{

if (recibido == true)

{

kont++;

contador.Text = kont.ToString();

recibido = false;

}

}

}

}

}



"RFOG" escribió en el mensaje
news:
Entonces el problema que tienes es que no te da tiempo a recibir los
datos y a actualizarlos en el mismo hilo, ¿no? Es decir, tienes un hilo
que hace una lectura del puerto serie y cuando tiene algo válido llama
al método que actualiza la función, y no te da tiempo a hacerlo.

Si es así, lo único que se me ocurre es que tengas dos hilos, uno para
recibir por el puerto serie y que coloque lo recibido en una cola, y
otro que vaya leyendo la cola y la vaya sacando por pantalla (y entonces
la cola irá creciendo y tendrás que decidir cuándo vaciarla e ignorar
ciertos mensajes)... pero pon el código del hilo, a ver si estuvieras
haciendo algo mal.

"Aitziber" escribió en el mensaje de noticias
news:O%
Bien, yo lo hago asi pero no me funciona correctamente.

Mi problema es que yo tengo un evento de recibir datos por linea serie.
Necesito hacer un hilo para ir mostrando por pantalla de la PDA (en
unos labels) y a su vez seguir recibiendo datos en el evento citado via
linea serie.

Si quieres te pongo el codigo que he hecho como ejemplo

"RFOG" escribió en el mensaje
news:
A ver, tu has dicho que quieres actualizar la UI desde un hilo, no cómo
hacer un hilo. Yo te he explicado cómo actualizar la UI desde un hilo,
es decir, desde ese hilo debes llamar a mi AddLog() y todo funcionará
perfectamente.

Ahora bien, si lo que quieres es saber cómo crear un hilo, eso es otra
cosa, y tienes muchas opciones, desde crearlo a mano, mediante el
componente Process o un ThreadPool... y algunas más seguro.

La forma más sencilla de crear un hilo es:

Declarar una variable de tipo Thread:

Thread miHilo;

Definir un método que va a ser el hilo en ejecución:

void Hilo(void)
{
while(!terminar)
{
//Hacer cosas
}
}

Y luego asignarlo donde quieras crearlo:

miThread=new Thread(Hilo);

Hay muchas otras formas de crear un hilo, pero esta es la más
sencilla.

Luego, cuando llames a

miThread.Start();

el hilo se lanzará, es decir, se ejecutará el método Hilo() hasta que
termine él solo o tu lo mantes.

Si haces

miThread.IsBackground=true;

el hilo se debe terminar solo cuando cierres la aplicación... aunque a
veces, si está enganchado en un objeto del núcleo (por ejemplo, un
puerto serie) no se termina, o al menos a mi a veces no se me ha
terminado, así que para cosas más o menos triviales, yo uso esto:
http://geeks.ms/blogs/rfog/archive/...ilos.aspx.
Aunque esté en C++/CLI el concepto se entiende, y si quieres comprobar
el código en C#, quita los "tejaícos" y cambia -> por . y :: por . y
debería compilarte en C#.


"Aitziber" escribió en el mensaje de noticias
news:
Pero de esta manera donde creas el hilo???
Thread mi_hilo.





"RFOG" escribió en el mensaje
news:
A ver. Si tienes un hilo, desde ese hilo no puedes acceder a los
controles de la ficha. En versiones anteriores a la 2.0, funcionaba
hasta que funcionaba y todo petaba. A partir de la 2.0 se genera una
excepción que te lo dice.

Para evitarlo, las fichas tienen un método que se llama Invoke
(http://msdn2.microsoft.com/es-es/li...hdc6b.aspx) y que
ejecuta un delegado en el hilo propietario de los controles (en
general el hilo principal). Entonces, para actualizar la UI
necesitas crearte un delegado y llamarlo con el Invoke de la ficha
desde tu hilo.

Si no sabes qué es un delegado, aquí lo tienes explicado:
http://msdn2.microsoft.com/es-es/li...sk6y.aspx.

Por lo tanto, el código de abajo declara un delegado que recibe una
cadena

private delegate void AddLogDelegate(string s);





Y luego clara una variable que va a contener el delegado

private AddLogDelegate m_addLog;





También declara un método que define el funcionamiento del delegado:

private void AddLogReal(string s)
{
m_lbLog.Items.Add(s);
m_lbLog.SelectedIndex = m_lbLog.Items.Count - 1;
}





En este caso, añade a un listbox la cadena pasada y coloca la
selección en esa misma cadena. En tu programa, pues cambiará los
valores del label.

Luego en el constructor de la ficha, asigna el delegado:

m_addLog=new AddLogDelegate(AddLogReal);





También crea otro método que será llamado por el hilo:

private void AddLog(string s)
{
Invoke(m_addLog, new string[] { s });
}





Luego, dentro del hilo en cuestión, se llama a

AddLog("Hola Mundo");

que a su vez llamará al método AddLogReal a través del Inoke de la
ficha, actualizando los controles pertinentes.

Tu te puedes ahorrar implementar el método AddLog y colocando su
contenido dentro del hilo cuando quieras actualizar esa parte de la
UI:

//tu hilo
this->Invoke(m_addLog, new string[] { "HOLA MUNDO" });

Y ya está.


"Aitziber" wrote in message
news:
NO entiendo muy bien como tengo que hacerlo.
Me lo podrias explicar un poco mas

"RFOG" escribió en el mensaje
news:
Hola.

No puedes actualizar directamente los label desde un hilo que no
sea el principal. Lo que tienes que hacer es llamar mediante el
método Invoke del form a un delegado que te hayas creado y que sea
el que actualice los label.

private delegate void AddLogDelegate(string s);
private AddLogDelegate m_addLog;
private void AddLog(string s)
{
Invoke(m_addLog, new string[] { s });
}
private void AddLogReal(string s)
{
m_lbLog.Items.Add(s);
m_lbLog.SelectedIndex = m_lbLog.Items.Count - 1;
}

El método AddLog() es llamado desde el hilo, que a su vez llama
mediante un Invoke a AddLogReal que es el que realmente hace el
trabajo.

el delegado m_addLog lo inicializo en el constructor de la ficha:

m_addLog=new AddLogDelegate(AddLogReal);

Así me evito estar asignando/borrando delegados todo el tiempo.

Depende de qué hagas, quizás te sea más interesante hacer la
llamada directamente desde el hilo en lugar de utilizar el método
AddLog...

"Aitziber" wrote in message
news:
Hola necesito saber como utilizar hilos en una aplicacion de
winform para pda.
Tengo una funcion que escribe en unos label... y quiero que esa
funcion sea un hilo y luego todo el programa que sea el hilo
principal.

Como puedo hacerlo??




Microsoft Visual C++ MVP
==>>>>>>>>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
>>>>>>>>> Buena cosa es tener amigos, pero mala el tener necesidad de ellos.








Microsoft Visual C++ MVP
==>>>>>>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
>>>>>>> Buena cosa es tener amigos, pero mala el tener necesidad de ellos.








Microsoft Visual C++ MVP
==>>>>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
>>>>> Flores pintadas, no huelen a nada.








Microsoft Visual C++ MVP
==>>> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
>>> Flores pintadas, no huelen a nada.








Microsoft Visual C++ MVP
==> Mi blog sobre programación: http://geeks.ms/blogs/rfog
Momentos Leves: http://momentosleves.blogspot.com/
Libros, ciencia ficción y programación
> La fuerza es el derecho de las bestias.

Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida