viernes, 05 de febrero de 2010 1:25
por
Cesar Reneses
Llamadas asíncronas con ADO.NET
En ciertas ocasiones, cuando trabajamos con grandes cantidades de datos al mismo tiempo las interfaces de nuestros programas pueden quedar bloqueadas. Esto generalmente hace que el usuario pierda la paciencia y termine cerrando la aplicación con la famosa combinación CTRL+ALT+SUPR.
Para evitarlo podemos hacer uso de los hilos de toda la vida o de la API asíncrona que nos ofrece ADO.NET:
Begin/EndExecuteNonQuery
Begin/EndExecuteReader
Begin/EndExecuteXmlReader
Es muy sencillo así que voy a mostrarlo con un ejemplo en el que hago múltiples inserciones en una tabla de la base de datos.
Lo primero que haremos es crear un objeto SqlConnection y otro SqlCommand:
SqlConnection conexion = new SqlConnection(@"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\nordwind\NORTHWND.MDF;Integrated Security=True; User Instance=True; asynchronous processing=true;");
SqlCommand cmd;
StringBuilder consulta = new StringBuilder();
Ahora abrimos la conexión con la base de datos y en un objeto StringBuilder añado todas las inserciones que tengo que hacer.
try
{
conexion.Open();
for(int i=0;i<palabras.Length;i++)
{
consulta.Append("INSERT into palabras (palabra) VALUES ('" + palabras
.ToString()+"');");
}
Cuando termina de crear todas las inserciones creo una instancia del SqlCommand al que le paso las inserciones y el objeto SqlConnection.
cmd = new SqlCommand(consulta.ToString(), conexion);
Para ejecutar el comando en otro hilo diferente al del programa principal preparo un delegado que se activara cuando termine la operación.
AsyncCallback callback = new AsyncCallback(MetodoCallBack);
Luego ejecuto el comando de forma asíncrona:
cmd.BeginExecuteNonQuery(callback, cmd);
Por último en la función que ejecuta el delegado recogemos el resultado de la operación y ejecutamos EndExecuteNonQuery.
SqlCommand cmd = (SqlCommand)result.AsyncState;
cmd.EndExecuteNonQuery(result);
El código completo sería el siguiente:
private void btnGuardar_Click(object sender, EventArgs e)
{
String[] palabras = txtTexto.Text.Split(" ".ToCharArray());
SqlConnection conexion = new SqlConnection(@"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\ORTHWND.MDF;Integrated Security=True; User Instance=True; asynchronous processing=true;");
SqlCommand cmd;
StringBuilder consulta = new StringBuilder();
try
{
conexion.Open();
for(int i=0;i<palabras.Length;i++)
{
consulta.Append("INSERT into palabras (palabra) VALUES ('" + palabras
.ToString()+"');");
}
cmd = new SqlCommand(consulta.ToString(), conexion);
AsyncCallback callback = new AsyncCallback(MetodoCallBack);
txtTexto.Enabled = false;
cmd.BeginExecuteNonQuery(callback, cmd);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void MetodoCallBack(IAsyncResult result)
{
SqlCommand cmd = (SqlCommand)result.AsyncState;
cmd.EndExecuteNonQuery(result);
txtTexto.Enabled = true;
cmd.Dispose();
}
Espero que os sirva.
Un saludo