I'm trying to figure out how delete a huge number of records from a DataGridView
, by delete I mean run a MySql delete query and remove the row itself from the DataGridView
. The issue is do all that without freeze the UI. I'm trying make it work with a BackgroundWorker
. I know it still need do a Invoke()
once a while and it still freeze the UI but those calls happen relatively fast and all the other other stuff keep going on background later, like the database deletion which is the most consuming-task. If there's a better to do that is very welcome.
My current implementation which obviously doesn't work, row.Index
is always -1
, is the following:
on click of button:
var rows = dataGridView1.SelectedRows;
backgroundWorker.RunWorkerAsync(rows);
then the backgroundWork's doWork event:
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
using (MySqlConnection con = Database.GetConnection())
{
using (MySqlCommand cmd = con.CreateCommand())
{
cmd.Connection = con;
con.Open();
var SelectedRows = e.Argument as DataGridViewSelectedRowCollection;
int rowIndex = 0;
int total = SelectedRows.Count;
foreach (DataGridViewRow row in SelectedRows)
{
int id = getIdByRow_safe(row.Index); //row.Index is -1
cmd.CommandText = string.Format("delete from xxx where id = {1}", id);
bool deleted = cmd.ExecuteNonQuery() == 1;
if (!deleted)
{
/* error handling ... */
}
int progress = (int)(100.0 / total * ++rowIndex);
BackgroundWorker.ReportProgress(progress, row);
}
}
}
}
and getId() function and family:
delegate int getIDEventHandler(int i);
int getIdByRow(int index)
{
return (int)dataGridView1.Rows[index].Cells["id"].Value;
}
int getIdByRow_safe(int index)
{
if (dataGridView1.InvokeRequired)
return (int) dataGridView1.Invoke(new getIDEventHandler(getIdByRow), new object[] { index });
return getIdByRow(index);
}
How do I fix this?