Saltar al contenido

Usar finalmente bloquea en el manejo de excepciones

Nuestros esfuerzos para que nuestro proveedor consiga que sus servidores sean perfectamente fiables continúan – todavía tenemos una ConnectionFailedException una vez a la semana – que, si lo piensas, no es realmente tan malo. Pero hay un problema con la forma en que se implementa la biblioteca del proveedor.

Si el procedimiento procede por el camino feliz:

Usar finalmente bloquea en el manejo de excepciones
Usar finalmente bloquea en el manejo de excepciones
12345678910var precioCliente =nuevoPrecioCliente();try{ precioCliente.Connect();var precio actualizado = precioCliente.GetPrice();return updatedPrice;}

csharp

Un enchufe, una conexión de red, se abre con la función Conectar y se cierra al final de GetPrice. Pero cuando ocurre una ConnectionFailedException, en GetPrice, el zócalo nunca se cierra, lo que significa que con el tiempo, estas conexiones muertas se acumulan y tu compañero de IT tiene que reiniciar el router cada pocas semanas para cerrarlas.

El vendedor conoce este problema, así que pone a disposición un método en su biblioteca para solucionarlo:

1precioCliente.ForzarCerrar();

Nuestro impulso inicial es simplemente colocar este código en el bloque de captura que está causando el problema:

12345678910catch(ConnectionFailedException connectionFailed){var serverName = connectionFailed.ServerName;// log servername details here priceClient.ForceClose();returnnull;}

csharp

Pero algo nos preocupa, la conexión se cierra en el camino feliz, ¿verdad? Creemos que sí, pero ¿estamos 100% seguros? Además, mientras tanto, nuestro manejador de errores de alto nivel ha detectado algunas excepciones de tiempo de espera de la conexión, donde, en lugar de fallar en la conexión, ésta tiene éxito pero tarda demasiado en responder:

1234catch(TimeoutException timeout){retorno;}

csharp

Supongo que si vamos a manejar esto en todas partes, tendremos que copiar y pegar la llamada ForceClose() en todas partes – y sabemos que copiar y pegar casi nunca es la respuesta correcta.

Esto es para lo que finalmente los bloques son para. Un bloque final es un código que siempre, siempre, siempre se ejecuta, ocurra o no una excepción.

Para hacer que nuestra llamada ForceClose() ejecute en todos los casos – el camino feliz y todos nuestros bloques de captura, lo añadimos al final así:

12345678910111213141516171819202122232425262728try{ precioCliente.Connect();var updatedPrice = precioCliente.GetPrice();return updatedPrice;}catch(InvalidCastException){returndecimal.Parse(precioCliente.ReturnedValue. Substring(1));}catch(TimeoutException timeout){returnnull;}catch(ConnectionFailedException connectionFailed){var serverName = connectionFailed.ServerName;// log servername details herereturnnull;}finally{ priceClient.ForceClose();}

csharp

¿Por qué no añadir simplemente ForceClose() al final fuera del manejo de errores, así?

1234567891011121314151617181920212223242526try{ precioCliente.Connect();var updatedPrice = precioCliente.GetPrice();return updatedPrice;}catch(InvalidCastException){returndecimal.Parse(precioCliente.ReturnedValue. Substring(1));}catch(TimeoutException timeout){returnnull;}catch(ConnectionFailedException connectionFailed){var serverName = connectionFailed.ServerName;// log servername details herereturnnull;}priceClient.ForceClose();

csharp

El problema son las declaraciones de retorno en los bloques de captura. Cuando la ejecución llega a esos puntos, pasa por alto todo lo que queda en el procedimiento, incluyendo otros bloques de captura. Incluir el bloque final asegura que su código de limpieza será ejecutado.