try catch Lento

17/09/2004 - 11:03 por Mark Elmer | Informe spam
Hola a todos.
Me he dado cuenta que cuando tu tienes un bloque Try catch
si algo va mal durante el proceso, este se ralentiza
muchisimo pero sólo la primera vez que ocurre.

por ejemplo si tenemos esto:
private void button1_Click(object sender, System.EventArgs
e)
{
object obj="patata";
int n=Convert.ToInt32(obj);
}
Si le damos al boton, la primera vez, el programa se queda
colgado durante aprox un segundo, a la segunda ya ni se
nota.
Alguien ha notado esto? sabeis a que se debe?
Gracias.

Mark Elmer

Preguntas similare

Leer las respuestas

#6 Pedro Luna Montalvo, MVP
18/09/2004 - 18:43 | Informe spam
b)

> El control de excepciones es vital. Pero debería combinarse con


prácticas
> defensivas, es decir: primero nos aseguramos de que todos los requisitos
> para la operación que vamos a ejecutar se satisfacen y luego llamamos a


la
> operación.

Y si los requisitos no se satisfacen, ¿qué haces? Para mí lo más adecuado


es
precisamente lanzar una excepción específica de nuestra


librería/componente,
que quien hace la llamada no deberá ignorar...



Saludos,

Disculpen por entrometerme.
Cuando Leonardo indicada "practicas defensivas", lo interprete precisamente
como tomar precauciones para evitar excepciones innecesarias. Por ejemplo,

try {
Ejecuto Accion que puede provocar excepcion
}
catch (Exception e) {
...hago algo...
throw new MiException("mi mensaje", e);
}

Esto me parece una practica un tanto perezosa (en el buen sentido), pues en
lo posible preferiria un codigo de este tipo:

try {
'Hago mis validaciones que provocarian una excepcion mas adelante
if (CondicionQueFallaria) {
throw new MiExcepcion("Mi mensaje");
}

Ejecuto Accion que puede provocar excepcion
}
catch (MiExcepcion) {
throw;
}
catch (Exception e) {
...hago algo...
throw new MiException("mi mensaje", e);
}

Esto me parece una actitud "defensiva", pues funcionalmente el resultado
seria el mismo, pero nos ahorraremos recursos debido a que no se dispararia
una excepcion adicional por la condicion de fallo.

Esta conversacion me parece muy provechosa e interesanteso like to hear
your comments ;)

Pedro Luna, MVP
Gye, Ecu


"Octavio Hernandez" escribió en el mensaje
news:
Hola, Leonardo!

a) En el mensaje anterior se me olvidó pegar la URL:

http://blogs.msdn.com/brada/archive...50403.aspx

b)

> El control de excepciones es vital. Pero debería combinarse con


prácticas
> defensivas, es decir: primero nos aseguramos de que todos los requisitos
> para la operación que vamos a ejecutar se satisfacen y luego llamamos a


la
> operación.

Y si los requisitos no se satisfacen, ¿qué haces? Para mí lo más adecuado


es
precisamente lanzar una excepción específica de nuestra


librería/componente,
que quien hace la llamada no deberá ignorar...

Saludos - Octavio

**********************************
"Leonardo Azpurua" <l e o n a r d o (arroba) m v p s (punto) o r g>


escribió
en el mensaje news:OoeG5%
>
> "Octavio Hernandez" escribió en el mensaje
> news:
> >
> > Buscando con Google sobre este tema me llevó a una interesante


discusión
> > sobre las excepciones entre Miguel de Icaza (Mono) y Brad Adams (.NET
CLR)
> > que recomiendo a todos...
> >
> > Yo personalmente no me corto al utilizar las excepciones por el hecho


de
> que
> > puedan ralentizar el programa, le doy más peso a la importancia
conceptual
> y
> > organizativa que estas ofrecen...
> >
> > Salu2 - Octavio
>
> Hola, Octavio:
>
> Sería bueno que incluyeras el vínculo a la discusión (puede ser
interesante
> leerla).
>
> El control de excepciones es vital. Pero debería combinarse con


prácticas
> defensivas, es decir: primero nos aseguramos de que todos los requisitos
> para la operación que vamos a ejecutar se satisfacen y luego llamamos a


la
> operación. Una excepción, entonces, debe producirse solo como


consecuencia
> de una causa imprevista -fallo de hardware, registro eliminado por otro
> usuario, bloqueo de un recurso-
>
> Es decir, las excepciones deben usarse para poder detectar condiciones
> excepcionales, pero no deberían reemplazar una buena técnica de
programación
> "defensiva", y deberían dispararse sólo de manera "excepcional".
>
> Salud!
>
> Leonardo
> mvp vb
>
>


Respuesta Responder a este mensaje
#7 Leonardo Azpurua
19/09/2004 - 06:28 | Informe spam
"Octavio Hernandez" escribió en el mensaje
news:
Hola, Leonardo!

a) En el mensaje anterior se me olvidó pegar la URL:

http://blogs.msdn.com/brada/archive...50403.aspx

b)

> El control de excepciones es vital. Pero debería combinarse con


prácticas
> defensivas, es decir: primero nos aseguramos de que todos los requisitos
> para la operación que vamos a ejecutar se satisfacen y luego llamamos a


la
> operación.

Y si los requisitos no se satisfacen, ¿qué haces? Para mí lo más adecuado


es
precisamente lanzar una excepción específica de nuestra


librería/componente,
que quien hace la llamada no deberá ignorar...



Hola, Octavio:

Muchas gracias por el link: lo leeré tan pronto como termine de responderte.

No me refería a las excepciones que lanzamos (son imprescindibles: no
queremos que el cliente de nuestra clase crea que todo salió bien cuando en
realidad hubo algun error), sino a las que recibimos.

Confiar TODO el manejo de errores a las excepciones puede producir un código
muy bonito, pero muy poco eficiente.

Por ejemplo:

try
{
x = imp.Factor * Rutas.GetRuta(cr).Tramos;
}
catch (Exception e) {
throw new Exception("Excepcion en CalculoImpuestoRuta:" +
ex.Message, ex);
}

Este codigo asume que Rutas.GetRuta(cr) devolvera una referencia valida a
algun tipo de objeto que expone una propiedad llamada Tramos.

Pero si GetRuta no devuelve un valor entonces obtendrás una excepcion
(NullReference), y deberas generar una excepcion.

Puedes perfectamente escribir:

Ruta r;
r = Rutas.GetRuta(cr);
if (r == null) {
throw new Exception("Ruta invalida en CalculoImpuestoRuta");
}

try {
x = imp.Factor * Rutas.GetRuta(cr).Tramos;
}
catch (Exception e) {
throw new Exception("Excepcion en CalculoImpuestoRuta:" +
ex.Message, ex);
}

El volumen del codigo aumenta (eso no es bueno), pero en caso de que <cr>
contenga una referencia a una ruta invalida, la excepcion es detectada y
procesada explicitamente antes de entrar en el bloque "controlado". De esta
manera, en vez de recibir una excepcion y tirarla hacia arriba, generas
directamente la excepcion (asegurándote de que el error no sea ignorado).

Por otra parte, si mi "cliente" es capaz de manjar las excepciones que yo le
mande, tambien sera capaz de manejar las excepciones que yo reciba, y las
excepciones almacenan información sobre la pila de llamadas en la que se
produjeron, de manera que es redundante que yo agregue mis mensajes.

El código, finalmente, quedaria así:

Ruta r;
r = Rutas.GetRuta(cr);
if (r == null) {
throw new Exception("Ruta invalida en CalculoImpuestoRuta");
}
x = imp.Factor * Rutas.GetRuta(cr).Tramos;

es decir: genero las excepciones que constituyan violaciones a mis
presupuestos (cr contiene un codigo de ruta valido), y dejo subir las
excepciones que se puedan haber generado "más abajo" (alguna en el calculo
de imp.Factor, por ejemplo).

Lo que hemos hecho ha sido descartar las causas conocidas de errores (el
unico, en este ejemplo tan simple, es la referencia invalida), y permitir
que los errores que nos lleguen sigan hacia arriba: nuestra responsabilidad
no es "fildear" los errores que se produzcan, sino asegurarnos de que no
sean ignorados.

Si podemos disparar una excepción, es porque asumimos que "el cliente" la
manejará. Igual que maneja las nuestras, deberá poder manejar las que
recibamos.

Pero verificando las precondiciones antes de entrar en los procesos tenemos
la capacidad de reducir la "cadena de excepciones", con una ganancia
considerable de eficiencia.

Salud!

Leonardo
mvp vb
Respuesta Responder a este mensaje
#8 Leonardo Azpurua
19/09/2004 - 06:43 | Informe spam
"Leonardo Azpurua" <l e o n a r d o (arroba) m v p s (punto) o r g> escribió
en el mensaje news:%
...
El código, finalmente, quedaria así:

Ruta r;
r = Rutas.GetRuta(cr);
if (r == null) {
throw new Exception("Ruta invalida en CalculoImpuestoRuta");
}
x = imp.Factor * Rutas.GetRuta(cr).Tramos;
...



En realidad debia ser:

Ruta r;
r = Rutas.GetRuta(cr);
if (r == null) {
throw new Exception("Ruta invalida en CalculoImpuestoRuta");
}
x = imp.Factor * r.Tramos;


Salud!
Respuesta Responder a este mensaje
#9 Octavio Hernandez
19/09/2004 - 16:40 | Informe spam
Hola, Leo (y Pedro también)!

a) Ante todo, un saludo.
b) En cuanto al ejemplo que mandas:

Ruta r;
r = Rutas.GetRuta(cr);
if (r == null) {
throw new Exception("Ruta invalida en CalculoImpuestoRuta");
}
x = imp.Factor * r.Tramos;

Aquí el problema está no en esta función, sino en GetRuta() y es más bien
semántico. ¿Que una ruta no exista es algo perfectamente aceptable, o es
algo que no debe ocurrir en circunstancias normales? En el primer caso, si
yo fuera el creador de la función devolvería null (y tu código estaría
perfecto), pero en el segundo lanzaría una excepción...

Lo que en ningún caso haría sería atrapar una posible excepción dentro de
GetRuta(), "tragármela" y devolver null... Pero si a un genio como Miguel
eso le parece adecuado, será que lo es. Todo en esta vida es relativo y
nadie tiene la verdad absoluta en sus manos.

c) En general, creo que ultimamente se habla demasiado de que las
excepciones afectan el rendimiento, y eso no es positivo para el concepto,
que es uno de los más importantes de toda la programación moderna, a mi modo
de ver. No sé si será cierto (como decía alguien en el hilo de discusión
citado) que la implementación de las excepciones de .NET es muy mala, o si
será un problema inherente al código y los heaps manejados (porque en muchos
años trabajando en C++ y Delphi jamás tuve problemas de rendimiento causados
por las excepciones, y he hecho uso y a veces abuso de ellas). En todo caso,
dentro de X años el hardware será muchas veces más rápido y el impacto de la
construcción de un objeto - mucho menor. El concepto seguirá siendo válido
(espero).

d) Pensando en lo de la "programación defensiva", creo que en general
tampoco estoy de acuerdo con vosotros. Aunque por supuesto, hay casos donde
hay que "defenderse" (si estás recibiendo entrada del usuario, por ejemplo).
Recuerdo que Stroustrup, que fue el que inventó las excepciones, siempre
alababa ese aspecto 'perezoso' (lazy) asociado a las excepciones que
mencionaba Pedro. Fíjense en el siguiente ejemplo. Supongan que tenemos que
programar una función que recibe un valor, le aplica la raíz cuadrada y lo
mutiplica por 3. ¿La programaríamos así:

double F1(double x)
{
if ( x < 0) throw new ExcepcionFormulas("Argumento ilegal");
return 3.0 * Math.Sqrt(x);
}

¿Para qué comprobar si x >= 0, si ya dentro de Sqrt() se hace? ¿Y si luego
otra función F2 llamara a F1, también lo comprobaríamos allí? Eso sí podría
ser un 'killer' para el rendimiento, pues las mismas comprobaciones se
estarían repetiendo a todos los niveles y en todas las llamadas, tanto
correctas como incorrectas.

Al menos en .NET tenemos Debug.Assert(), con el que podríamos 'resolver' el
asunto... Aunque yo hubiera preferido que Assert lanzara una excepción en
vez de imprimir un mensaje. Hay una implementación así en:

http://www.codeproject.com/csharp/d...ntract.asp

e) Finalmente, decir que este intercambio de criterios me resulta
tremendamente interesante. Mi idea no es discutir por discutir ni intentar
imponer mi opinión, sino lo contrario - aprender de los demás.

Salu2 - Octavio

***************************************************
"Leonardo Azpurua" <l e o n a r d o (arroba) m v p s (punto) o r g> escribió
en el mensaje news:%
"Octavio Hernandez" escribió en el mensaje
news:
> Hola, Leonardo!
>
> a) En el mensaje anterior se me olvidó pegar la URL:
>
> http://blogs.msdn.com/brada/archive...50403.aspx
>
> b)
>
> > El control de excepciones es vital. Pero debería combinarse con
prácticas
> > defensivas, es decir: primero nos aseguramos de que todos los


requisitos
> > para la operación que vamos a ejecutar se satisfacen y luego llamamos


a
la
> > operación.
>
> Y si los requisitos no se satisfacen, ¿qué haces? Para mí lo más


adecuado
es
> precisamente lanzar una excepción específica de nuestra
librería/componente,
> que quien hace la llamada no deberá ignorar...

Hola, Octavio:

Muchas gracias por el link: lo leeré tan pronto como termine de


responderte.

No me refería a las excepciones que lanzamos (son imprescindibles: no
queremos que el cliente de nuestra clase crea que todo salió bien cuando


en
realidad hubo algun error), sino a las que recibimos.

Confiar TODO el manejo de errores a las excepciones puede producir un


código
muy bonito, pero muy poco eficiente.

Por ejemplo:

try
{
x = imp.Factor * Rutas.GetRuta(cr).Tramos;
}
catch (Exception e) {
throw new Exception("Excepcion en CalculoImpuestoRuta:" +
ex.Message, ex);
}

Este codigo asume que Rutas.GetRuta(cr) devolvera una referencia valida a
algun tipo de objeto que expone una propiedad llamada Tramos.

Pero si GetRuta no devuelve un valor entonces obtendrás una excepcion
(NullReference), y deberas generar una excepcion.

Puedes perfectamente escribir:

Ruta r;
r = Rutas.GetRuta(cr);
if (r == null) {
throw new Exception("Ruta invalida en CalculoImpuestoRuta");
}

try {
x = imp.Factor * Rutas.GetRuta(cr).Tramos;
}
catch (Exception e) {
throw new Exception("Excepcion en CalculoImpuestoRuta:" +
ex.Message, ex);
}

El volumen del codigo aumenta (eso no es bueno), pero en caso de que <cr>
contenga una referencia a una ruta invalida, la excepcion es detectada y
procesada explicitamente antes de entrar en el bloque "controlado". De


esta
manera, en vez de recibir una excepcion y tirarla hacia arriba, generas
directamente la excepcion (asegurándote de que el error no sea ignorado).

Por otra parte, si mi "cliente" es capaz de manjar las excepciones que yo


le
mande, tambien sera capaz de manejar las excepciones que yo reciba, y las
excepciones almacenan información sobre la pila de llamadas en la que se
produjeron, de manera que es redundante que yo agregue mis mensajes.

El código, finalmente, quedaria así:

Ruta r;
r = Rutas.GetRuta(cr);
if (r == null) {
throw new Exception("Ruta invalida en CalculoImpuestoRuta");
}
x = imp.Factor * Rutas.GetRuta(cr).Tramos;

es decir: genero las excepciones que constituyan violaciones a mis
presupuestos (cr contiene un codigo de ruta valido), y dejo subir las
excepciones que se puedan haber generado "más abajo" (alguna en el calculo
de imp.Factor, por ejemplo).

Lo que hemos hecho ha sido descartar las causas conocidas de errores (el
unico, en este ejemplo tan simple, es la referencia invalida), y permitir
que los errores que nos lleguen sigan hacia arriba: nuestra


responsabilidad
no es "fildear" los errores que se produzcan, sino asegurarnos de que no
sean ignorados.

Si podemos disparar una excepción, es porque asumimos que "el cliente" la
manejará. Igual que maneja las nuestras, deberá poder manejar las que
recibamos.

Pero verificando las precondiciones antes de entrar en los procesos


tenemos
la capacidad de reducir la "cadena de excepciones", con una ganancia
considerable de eficiencia.

Salud!

Leonardo
mvp vb


email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una pregunta AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida