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:nordwindNORTHWND.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[i].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[i].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