Reputation: 364
Im trying to populate a datagridview from a query of sql but it takes a long time , what im trying to do is show a .gif "loading" meanwhile is populating the grid, im using threads but the .gif freezes , and if I use the CheckForIllegalCrossThreadCalls = false;
the datagridview doesnt load the scroll bar acts weird. here is my code
delegate void CambiarProgresoDelegado();
BUTTON CLICK
private void btn_busca_Click(object sender, EventArgs e)
{
pictureBox1.Visible = true;
thread= new Thread(new ThreadStart(ejecuta_sql));
thread.Start();
}
method
private void ejecuta_sql()
{
if (this.InvokeRequired)
{
CambiarProgresoDelegado delegado = new CambiarProgresoDelegado(ejecuta_sql);
object[] parametros = new object[] { };
this.Invoke(delegado, parametros);
}
else
{
myConnection.Open();
SqlCommand sql_command2;
DataSet dt2 = new DataSet();
sql_command2 = new SqlCommand("zzhoy", myConnection);
sql_command2.CommandType = CommandType.StoredProcedure;
sql_command2.Parameters.AddWithValue("@FechaIni", dateTimePicker1.Value.ToShortDateString());
sql_command2.Parameters.AddWithValue("@FechaFin", dateTimePicker2.Value.ToShortDateString());
SqlDataAdapter da2 = new SqlDataAdapter(sql_command2);
da2.Fill(dt2, "tbl1");
grid_detalle.DataSource = dt2.Tables[0];
myConnection.Close();
pictureBox1.Visible = false;
}
and the .gif freezes until the thread finish his job.
Upvotes: 1
Views: 8252
Reputation: 41
You may consider changing your approach, especially if you are doing a lot of GUI updates from your background threads. Reasons:
What I prefer is to do polling the background thread data instead. Set up GUI timer for say 300ms, then check if there is any data ready to be updated, then do quick update with proper locking.
Here is code example:
private string text = "";
private object lockObject = new object();
private void MyThread()
{
while (true)
{
lock (lockObject)
{
// That can be any code that calculates text variable,
// I'm using DateTime for demonstration:
text = DateTime.Now.ToString();
}
}
}
private void timer_Tick(object sender, EventArgs e)
{
lock(lockObject)
{
label.Text = text;
}
}
Note, that while the text variable is updated very frequently the GUI still stays responsive. If, instead, you update GUI on each "text" change, your system will freeze.
Upvotes: 2
Reputation: 39142
You created a thread but then immediately made the code switch back to the main UI thread with Invoke(), negating any benefits of making the thread in the first place.
Run the query on the other thread, then Invoke() just the part that updates the UI:
private string FechaIni;
private string FechaFin;
private void btn_busca_Click(object sender, EventArgs e)
{
btn_busca.Enabled = false;
pictureBox1.Visible = true;
FechaIni = dateTimePicker1.Value.ToShortDateString();
FechaFin = dateTimePicker2.Value.ToShortDateString();
thread = new Thread(new ThreadStart(ejecuta_sql));
thread.Start();
}
private void ejecuta_sql()
{
myConnection.Open();
SqlCommand sql_command2;
DataSet dt2 = new DataSet();
sql_command2 = new SqlCommand("zzhoy", myConnection);
sql_command2.CommandType = CommandType.StoredProcedure;
sql_command2.Parameters.AddWithValue("@FechaIni", FechaIni);
sql_command2.Parameters.AddWithValue("@FechaFin", FechaFin);
SqlDataAdapter da2 = new SqlDataAdapter(sql_command2);
da2.Fill(dt2, "tbl1");
myConnection.Close();
this.Invoke((MethodInvoker)delegate {
grid_detalle.DataSource = dt2.Tables[0];
pictureBox1.Visible = false;
btn_busca.Enabled = true;
});
}
Upvotes: 3