Evitar se me "congele" mi aplicacion

22/07/2008 - 16:10 por Rick | Informe spam
Que tal foro, una duda

Tengo una aplicacion que carga datos de una db, es un SP, que se tarda unos
segundos en ejecutarse, se carga cuando inicia la app y pues no hay lio, el
problema es que despues, por medio de un timer cada 5 o 10 segundos, mando
llamar de nuevo a ese SP y mientras se ejecuta la aplicacion se congela, no
sigue su ejecucion normal, hasta que termina de ejecutarse el SP ya puedes
seguir trabajando, pero dado el timer pues es muy latoso que cada X segundos
se congele la aplicacion, intenté llamar a ese SP por medio de un
backgroundworker y nada, hace lo mismo (se congela por X segundos), por
medio de un hilo y tampoco =(


Que otra opcion tengo? o que me recomiendan hacer?


Saludos!!

Preguntas similare

Leer las respuestas

#1 Alberto Poblacion
22/07/2008 - 17:34 | Informe spam
"Rick" wrote in message
news:
Tengo una aplicacion que carga datos de una db, es un SP, que se tarda
unos segundos en ejecutarse, se carga cuando inicia la app y pues no hay
lio, el problema es que despues, por medio de un timer cada 5 o 10
segundos, mando llamar de nuevo a ese SP y mientras se ejecuta la
aplicacion se congela, no sigue su ejecucion normal, hasta que termina de
ejecutarse el SP ya puedes seguir trabajando, pero dado el timer pues es
muy latoso que cada X segundos se congele la aplicacion, intenté llamar a
ese SP por medio de un backgroundworker y nada, hace lo mismo (se congela
por X segundos), por medio de un hilo y tampoco =(



Algo tienes que estar haciendo mal. Tanto el BackgroundWorker como el
hilo te permiten que la aplicación siga funcionando mientras se ejecuta el
procedimiento, si los usas correctamente.

Que otra opcion tengo?



Si tienes el Framework 2.0 o posterior, también puedes usar los métodos
asíncronos de ado.net, como por ejemplo el BeginExecuteNonQuery junto con su
EndExecuteNonQuery. Al igual que el BackgroundWorker y el Hilo, hay que
usarlo correctamente, por ejemplo, si llamas al EndExecuteNonQuery antes de
que haya concluido la ejecución del procedimiento, el programa se
"congelará" como si no hubieses empleado el método asíncrono.
Respuesta Responder a este mensaje
#2 Rick
22/07/2008 - 23:12 | Informe spam
Ok, mira lo que hago es esto:


private void tmrCteExtra_Tick(object sender, EventArgs e)

{

//AGREGAR CLIENTES QUE NO ESTABAN CONECTADOS POR EL SP

if(backgroundWorker1.IsBusy==false)

backgroundWorker1.RunWorkerAsync();

//AGREGAR CLIENTES QUE NO ESTABAN CONECTADOS POR EL SP

}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)

{

this.AgregaNuevoCte();

}

private void AgregaNuevoCte()

{

NpgsqlConnection Cnn = new
NpgsqlConnection(Properties.Settings.Default.PgSQLCnn);

NpgsqlCommand Cmd = new NpgsqlCommand("",Cnn);

NpgsqlDataReader rdr;

Int32 liImg = 0; ;

String lsEstado = "";

Boolean encontrado = false;

try

{

Cnn.Open();

Cmd.CommandText = "select * from web_lista_users ('" + gsCve_Usuario +
"','G',0,'E') order by cve_user";

rdr = Cmd.ExecuteReader();

while (rdr.Read())

{

encontrado = false;

for (int i = 0; i < tvCliente.Nodes[0].Nodes.Count; i++)

{

if (rdr["usuario"].ToString() == tvCliente.Nodes[0].Nodes[i].Text)

{

encontrado = true;

}

}

if (!encontrado)

{

liImg = 1;

lsEstado = "En Linea";

TreeNode Nodo = new TreeNode(rdr["usuario"].ToString(), liImg, liImg);

Nodo.ToolTipText = lsEstado;

Nodo.Tag = rdr["cve_user"].ToString();

tvCliente.Nodes[0].Nodes.Add(Nodo);

}

}

rdr.Close();

tvCliente.ExpandAll();

}

catch (Exception ex)

{

MessageBox.Show(ex.Message + "El sistema se cerrar ahora.");//+
"f1-load");

this.Close();

}

finally {

if (Cnn.State == ConnectionState.Open) { Cnn.Close(); }

}

}


Como vez, solo agrego a un treeview, pero nada de endexecute ni nada por el
estilo =(

"Alberto Poblacion"
escribió en el mensaje news:%
"Rick" wrote in message
news:
Tengo una aplicacion que carga datos de una db, es un SP, que se tarda
unos segundos en ejecutarse, se carga cuando inicia la app y pues no hay
lio, el problema es que despues, por medio de un timer cada 5 o 10
segundos, mando llamar de nuevo a ese SP y mientras se ejecuta la
aplicacion se congela, no sigue su ejecucion normal, hasta que termina de
ejecutarse el SP ya puedes seguir trabajando, pero dado el timer pues es
muy latoso que cada X segundos se congele la aplicacion, intenté llamar a
ese SP por medio de un backgroundworker y nada, hace lo mismo (se congela
por X segundos), por medio de un hilo y tampoco =(



Algo tienes que estar haciendo mal. Tanto el BackgroundWorker como el
hilo te permiten que la aplicación siga funcionando mientras se ejecuta el
procedimiento, si los usas correctamente.

Que otra opcion tengo?



Si tienes el Framework 2.0 o posterior, también puedes usar los métodos
asíncronos de ado.net, como por ejemplo el BeginExecuteNonQuery junto con
su EndExecuteNonQuery. Al igual que el BackgroundWorker y el Hilo, hay que
usarlo correctamente, por ejemplo, si llamas al EndExecuteNonQuery antes
de que haya concluido la ejecución del procedimiento, el programa se
"congelará" como si no hubieses empleado el método asíncrono.

Respuesta Responder a este mensaje
#3 Alberto Poblacion
23/07/2008 - 09:08 | Informe spam
"Rick" wrote in message
news:%23tHdp%
Ok, mira lo que hago es esto: [...]



En principio, el mecanismo de llamada que has hecho parece correcto, y
la operación de acceso a base de datos debería estarse realizando en el hilo
del backgroundworker sin bloquear el hilo de la interfaz de usuario. Por lo
menos, no detecto nada que lo impida con un examen visual del código que has
puesto.

Como ves, solo agrego a un treeview



Puede que el problema esté ahi. La insterfaz de usuario en Windows Forms
es monohilo, lo que significa que no se pueden manipular los elementos de
pantalla (como el TreeView) desde un hilo distinto. Fíjate bien que en la
documentación del backgroundworker te lo advierte expresamente: "Note: You
must be careful not to manipulate any user-interface objects in your DoWork
event handler. Instead, communicate to the user interface through the
ProgressChanged and RunWorkerCompleted events." Y si en vez del
BackgroundWorker utilizaras un Hilo o un método asíncrono, te ocurriría
exactamente lo mismo aunque la documentación no lo advierta.

Lo que tienes que hacer es usar el segundo hilo para guardar en
variables los resultados de la consulta a base de datos, y una vez que
tengas los datos, pasárselos al hilo principal para que éste los traslade a
pantalla. La documentación del BackgroundWorker te explica cómo hacer este
paso al hilo principal: usando los eventos ProgressChanged o
RunWorkerCompleted. Si en lugar del BackgroundWorker estuvieras usando un
Thread, el paso al hilo principal lo harías con un this.Invoke(rutina).

Si a pesar de eso se te sigue bloqueando, tendrás que usar el
"debugger" sobre tu código fuente para ver dónde se bloquea y determinar
paso a paso cómo se ha llegado a esa situación.
Respuesta Responder a este mensaje
#4 Rick
25/07/2008 - 01:23 | Informe spam
Okas dejame intentar a ver que pasa

Saludos!!!

"Alberto Poblacion"
escribió en el mensaje news:
"Rick" wrote in message
news:%23tHdp%
Ok, mira lo que hago es esto: [...]



En principio, el mecanismo de llamada que has hecho parece correcto, y
la operación de acceso a base de datos debería estarse realizando en el
hilo del backgroundworker sin bloquear el hilo de la interfaz de usuario.
Por lo menos, no detecto nada que lo impida con un examen visual del
código que has puesto.

Como ves, solo agrego a un treeview



Puede que el problema esté ahi. La insterfaz de usuario en Windows
Forms es monohilo, lo que significa que no se pueden manipular los
elementos de pantalla (como el TreeView) desde un hilo distinto. Fíjate
bien que en la documentación del backgroundworker te lo advierte
expresamente: "Note: You must be careful not to manipulate any
user-interface objects in your DoWork event handler. Instead, communicate
to the user interface through the ProgressChanged and RunWorkerCompleted
events." Y si en vez del BackgroundWorker utilizaras un Hilo o un método
asíncrono, te ocurriría exactamente lo mismo aunque la documentación no lo
advierta.

Lo que tienes que hacer es usar el segundo hilo para guardar en
variables los resultados de la consulta a base de datos, y una vez que
tengas los datos, pasárselos al hilo principal para que éste los traslade
a pantalla. La documentación del BackgroundWorker te explica cómo hacer
este paso al hilo principal: usando los eventos ProgressChanged o
RunWorkerCompleted. Si en lugar del BackgroundWorker estuvieras usando un
Thread, el paso al hilo principal lo harías con un this.Invoke(rutina).

Si a pesar de eso se te sigue bloqueando, tendrás que usar el
"debugger" sobre tu código fuente para ver dónde se bloquea y determinar
paso a paso cómo se ha llegado a esa situación.

Respuesta Responder a este mensaje
#5 alfonso_C#
29/07/2008 - 02:30 | Informe spam
On 24 jul, 19:23, "Rick" wrote:
Okas dejame intentar a ver que pasa

Saludos!!!

"Alberto Poblacion"
escribió en el mensajenews:

> "Rick" wrote in message
>news:%23tHdp%
>> Ok, mira lo que hago es esto: [...]

>    En principio, el mecanismo de llamada que has hecho parece correcto, y
> la operación de acceso a base de datos debería estarse realizando en el
> hilo del backgroundworker sin bloquear el hilo de la interfaz de usuario.
> Por lo menos, no detecto nada que lo impida con un examen visual del
> código que has puesto.

>> Como ves, solo agrego a un treeview

>    Puede que el problema esté ahi. La insterfaz de usuario en Windows
> Forms es monohilo, lo que significa que no se pueden manipular los
> elementos de pantalla (como el TreeView) desde un hilo distinto. Fíjate
> bien que en la documentación del backgroundworker te lo advierte
> expresamente: "Note: You must be careful not to manipulate any
> user-interface objects in your DoWork event handler. Instead, communicate
> to the user interface through the ProgressChanged and RunWorkerCompleted
> events." Y si en vez del BackgroundWorker utilizaras un Hilo o un método
> asíncrono, te ocurriría exactamente lo mismo aunque la documentación no lo
> advierta.

>     Lo que tienes que hacer es usar el segundo hilo para guardar en
> variables los resultados de la consulta a base de datos, y una vez que
> tengas los datos, pasárselos al hilo principal para que éste los traslade
> a pantalla. La documentación del BackgroundWorker te explica cómo hacer
> este paso al hilo principal: usando los eventos ProgressChanged o
> RunWorkerCompleted. Si en lugar del BackgroundWorker estuvieras usando un
> Thread, el paso al hilo principal lo harías con un this.Invoke(rutina).

>     Si a pesar de eso se te sigue bloqueando, tendrás que usar el
> "debugger" sobre tu código fuente para ver dónde se bloquea y determinar
> paso a paso cómo se ha llegado a esa situación.





Lo que te propone Alberto es correcto debes usar el evento
RunWorkerCompleted del Backgroundworker para pasar el control al hilo
principal. A mi me sucedia lo mismo y usandolo de este modo todo ha
funcionado muy bien.
email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida