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

#16 Aitziber
10/04/2008 - 16:58 | Informe spam
Me pasa que el programa se conecta con una placa electronica.
Al conectarme con el cable mediante linea serie, me va perfecto el programa,
pero al hacerlo con el bluetooth (que es lo que tengo que hacer) me va peor.
Es como si fuera mas lento y no le diese tiempo a coger todos los mensajes.
Por eso quiero hacer el programa lo mas rápido posible.


"RFOG" escribió en el mensaje
news:
¿Qué va peor? Es decir, funcionar, funciona, ¿no? No peta ni hace cosas
raras.

¿Lo puedes ejecutar en un PC? Es decir, el exe para la PDA debe funcionar
sin problemas en el PC (se verá feo, pero funcionará?

En Thu, 10 Apr 2008 16:13:19 +0200, Aitziber
escribió:

Lo he hecho pero la verdad es que no se si lo he hecho bien porque se
supone
que tiene que ir mejor pero a mi me da la sensacion que me va peor.
Te importaria que te mande mi codigo??

"RFOG" escribió en el mensaje
news:
En Thu, 10 Apr 2008 15:22:49 +0200, Aitziber
escribió:

Vale hasta ahi entiendo.
Ahora voy con mi programa.
Tengo un data received que hace un invoke a una funcion y en esa
funcion
se
responde via linea serie.



No necesitas hacer invoke ahí siempre y cuando esa función que responda
no
lea/escriba de la UI-

Despues esa funcion llama a otra funcion que es la que quiero que se
ejecute
a la vez que el data received y la funcion primera.
Me explico??



Sí. Es en esa segunda función donde debes hacer el invoke para
actualizar
la UI. Algo así:

void DataReceivedEvento()
{
Responder();
}
void Responder()
{
//bla bla
...
Invoke(métodoQueAccedeALaUI);
}

"RFOG" escribió en el mensaje
news:
Pero el Invoke lo tienes en un hilo que hace un invoke y termina...

En Thu, 10 Apr 2008 15:13:31 +0200, Aitziber
escribió:

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.
romano.










Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/









Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/









Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/
Respuesta Responder a este mensaje
#17 Aitziber
10/04/2008 - 17:04 | Informe spam
puedes ver mi codigo aqui:
http://forums.microsoft.com/MSDN-ES...amp;SiteID&mode=1


"RFOG" escribió en el mensaje
news:
¿Qué va peor? Es decir, funcionar, funciona, ¿no? No peta ni hace cosas
raras.

¿Lo puedes ejecutar en un PC? Es decir, el exe para la PDA debe funcionar
sin problemas en el PC (se verá feo, pero funcionará?

En Thu, 10 Apr 2008 16:13:19 +0200, Aitziber
escribió:

Lo he hecho pero la verdad es que no se si lo he hecho bien porque se
supone
que tiene que ir mejor pero a mi me da la sensacion que me va peor.
Te importaria que te mande mi codigo??

"RFOG" escribió en el mensaje
news:
En Thu, 10 Apr 2008 15:22:49 +0200, Aitziber
escribió:

Vale hasta ahi entiendo.
Ahora voy con mi programa.
Tengo un data received que hace un invoke a una funcion y en esa
funcion
se
responde via linea serie.



No necesitas hacer invoke ahí siempre y cuando esa función que responda
no
lea/escriba de la UI-

Despues esa funcion llama a otra funcion que es la que quiero que se
ejecute
a la vez que el data received y la funcion primera.
Me explico??



Sí. Es en esa segunda función donde debes hacer el invoke para
actualizar
la UI. Algo así:

void DataReceivedEvento()
{
Responder();
}
void Responder()
{
//bla bla
...
Invoke(métodoQueAccedeALaUI);
}

"RFOG" escribió en el mensaje
news:
Pero el Invoke lo tienes en un hilo que hace un invoke y termina...

En Thu, 10 Apr 2008 15:13:31 +0200, Aitziber
escribió:

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.
romano.










Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/









Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/









Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/
Respuesta Responder a este mensaje
#18 RFOG
10/04/2008 - 17:21 | Informe spam
¿La velocidad de conexión es la misma, es decir, son los mismos baudios
tanto el puerto serie como el bt? Si es sí, prueba a medir la cantidad de
mensajes que recibes, es decir, en lugar de sacar nada por pantalla,
simplemente lanza el programa con un contador de mensajes recibidos,
cuando haya pasado x tiempo, lo pausas con el debugger y miras el contador.

Yo casi te diría que está fallando la conexión con el bt y recibes menos
mensajes por bt o que éstos están mal formados.

Pero si quieres la mayor velocidad posible, tienes que olvidarte del
evento DataReceived, eso es más lento que el caballo del malo.

Te creas un hilo:

Thread hilo=new Thread(LeerSerie);
hilo.IsBackground=true;
hilo.Start();
...

void LeerSerie(void)
{
for(;;)
{
if(puertoSerie->BytesToRead)
{
//usar la función más adecuada para leer lo que tengas que leer.
}
//procesa la respuesta y responde

//y luego...
Invoke(métodoQueAccedeALaUI);
}
Thread.Sleep(1); //Que no se te olvide esto
}

Esta es la forma más rápida que creo que hay sin entrar en alturas... Si
así no te da a basto a trastear con los mensajes, puedes sustituir el
Invoke por un BeginInvoke del delegado... Lo tienes explicado aquí:
http://geeks.ms/blogs/rfog/archive/...hilos.aspx
(gcnew en C++/CLI es new en C#, por lo demás, lo mismo con los tejaícos y
las flechas). Si lo haces así y es un tema de velocidades, como en algún
momento no pares de recibir mensajes por el puerto serie, terminarás
tumbando la PDA...


En Thu, 10 Apr 2008 16:58:14 +0200, Aitziber escribió:

Me pasa que el programa se conecta con una placa electronica.
Al conectarme con el cable mediante linea serie, me va perfecto el
programa,
pero al hacerlo con el bluetooth (que es lo que tengo que hacer) me va
peor.
Es como si fuera mas lento y no le diese tiempo a coger todos los
mensajes.
Por eso quiero hacer el programa lo mas rápido posible.


"RFOG" escribió en el mensaje
news:
¿Qué va peor? Es decir, funcionar, funciona, ¿no? No peta ni hace cosas
raras.

¿Lo puedes ejecutar en un PC? Es decir, el exe para la PDA debe
funcionar
sin problemas en el PC (se verá feo, pero funcionará?

En Thu, 10 Apr 2008 16:13:19 +0200, Aitziber
escribió:

Lo he hecho pero la verdad es que no se si lo he hecho bien porque se
supone
que tiene que ir mejor pero a mi me da la sensacion que me va peor.
Te importaria que te mande mi codigo??

"RFOG" escribió en el mensaje
news:
En Thu, 10 Apr 2008 15:22:49 +0200, Aitziber
escribió:

Vale hasta ahi entiendo.
Ahora voy con mi programa.
Tengo un data received que hace un invoke a una funcion y en esa
funcion
se
responde via linea serie.



No necesitas hacer invoke ahí siempre y cuando esa función que
responda
no
lea/escriba de la UI-

Despues esa funcion llama a otra funcion que es la que quiero que se
ejecute
a la vez que el data received y la funcion primera.
Me explico??



Sí. Es en esa segunda función donde debes hacer el invoke para
actualizar
la UI. Algo así:

void DataReceivedEvento()
{
Responder();
}
void Responder()
{
//bla bla
...
Invoke(métodoQueAccedeALaUI);
}

"RFOG" escribió en el mensaje
news:
Pero el Invoke lo tienes en un hilo que hace un invoke y termina...

En Thu, 10 Apr 2008 15:13:31 +0200, Aitziber
escribió:

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.
romano.










Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/









Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/









Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/









Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/
Respuesta Responder a este mensaje
#19 RFOG
10/04/2008 - 17:29 | Informe spam
Ahora he entendido el Invoke que haces en ThreadProc... y sigue estando
mal, ya que estás llamando a mi_hilo que entra en un bucle que actualiza
la UI: estás actualizando la UI desde un hilo diferente al principal...
posiblemente dejando pajarito al hilo principal...

Respecto al código del tratamiento de las comunicaciones no lo veo mal...
deberías probar primero sin actualizar la UI a ver si te da tiempo a
hacerlo todo...

En Thu, 10 Apr 2008 17:04:04 +0200, Aitziber escribió:

puedes ver mi codigo aqui:
http://forums.microsoft.com/MSDN-ES...amp;SiteID&mode=1


"RFOG" escribió en el mensaje
news:
¿Qué va peor? Es decir, funcionar, funciona, ¿no? No peta ni hace cosas
raras.

¿Lo puedes ejecutar en un PC? Es decir, el exe para la PDA debe
funcionar
sin problemas en el PC (se verá feo, pero funcionará?

En Thu, 10 Apr 2008 16:13:19 +0200, Aitziber
escribió:

Lo he hecho pero la verdad es que no se si lo he hecho bien porque se
supone
que tiene que ir mejor pero a mi me da la sensacion que me va peor.
Te importaria que te mande mi codigo??

"RFOG" escribió en el mensaje
news:
En Thu, 10 Apr 2008 15:22:49 +0200, Aitziber
escribió:

Vale hasta ahi entiendo.
Ahora voy con mi programa.
Tengo un data received que hace un invoke a una funcion y en esa
funcion
se
responde via linea serie.



No necesitas hacer invoke ahí siempre y cuando esa función que
responda
no
lea/escriba de la UI-

Despues esa funcion llama a otra funcion que es la que quiero que se
ejecute
a la vez que el data received y la funcion primera.
Me explico??



Sí. Es en esa segunda función donde debes hacer el invoke para
actualizar
la UI. Algo así:

void DataReceivedEvento()
{
Responder();
}
void Responder()
{
//bla bla
...
Invoke(métodoQueAccedeALaUI);
}

"RFOG" escribió en el mensaje
news:
Pero el Invoke lo tienes en un hilo que hace un invoke y termina...

En Thu, 10 Apr 2008 15:13:31 +0200, Aitziber
escribió:

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.
romano.










Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/









Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/









Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/









Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/
Respuesta Responder a este mensaje
#20 Aitziber
14/04/2008 - 14:48 | Informe spam
HOla,

No lo consigo. no se que mas hacer.

Si abria alguna manera de mandarte mi codigo entero para que lo veas...



"RFOG" escribió en el mensaje
news:
Ahora he entendido el Invoke que haces en ThreadProc... y sigue estando
mal, ya que estás llamando a mi_hilo que entra en un bucle que actualiza
la UI: estás actualizando la UI desde un hilo diferente al principal...
posiblemente dejando pajarito al hilo principal...

Respecto al código del tratamiento de las comunicaciones no lo veo mal...
deberías probar primero sin actualizar la UI a ver si te da tiempo a
hacerlo todo...

En Thu, 10 Apr 2008 17:04:04 +0200, Aitziber
escribió:

puedes ver mi codigo aqui:
http://forums.microsoft.com/MSDN-ES...amp;SiteID&mode=1


"RFOG" escribió en el mensaje
news:
¿Qué va peor? Es decir, funcionar, funciona, ¿no? No peta ni hace cosas
raras.

¿Lo puedes ejecutar en un PC? Es decir, el exe para la PDA debe
funcionar
sin problemas en el PC (se verá feo, pero funcionará?

En Thu, 10 Apr 2008 16:13:19 +0200, Aitziber
escribió:

Lo he hecho pero la verdad es que no se si lo he hecho bien porque se
supone
que tiene que ir mejor pero a mi me da la sensacion que me va peor.
Te importaria que te mande mi codigo??

"RFOG" escribió en el mensaje
news:
En Thu, 10 Apr 2008 15:22:49 +0200, Aitziber
escribió:

Vale hasta ahi entiendo.
Ahora voy con mi programa.
Tengo un data received que hace un invoke a una funcion y en esa
funcion
se
responde via linea serie.



No necesitas hacer invoke ahí siempre y cuando esa función que
responda
no
lea/escriba de la UI-

Despues esa funcion llama a otra funcion que es la que quiero que se
ejecute
a la vez que el data received y la funcion primera.
Me explico??



Sí. Es en esa segunda función donde debes hacer el invoke para
actualizar
la UI. Algo así:

void DataReceivedEvento()
{
Responder();
}
void Responder()
{
//bla bla
...
Invoke(métodoQueAccedeALaUI);
}

"RFOG" escribió en el mensaje
news:
Pero el Invoke lo tienes en un hilo que hace un invoke y termina...

En Thu, 10 Apr 2008 15:13:31 +0200, Aitziber
escribió:

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.
romano.










Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/









Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/









Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/









Usando el revolucionario cliente de correo de Opera:
http://www.opera.com/mail/
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida