2015-01-07 104 views
0

我试着去填充从SQL的查询datagridview的,但它需要很长的时间,什么即时试图做的是显示一个.gif“加载”同时被填充网格,使用im线程但.gif冻结,如果我使用CheckForIllegalCrossThreadCalls = false; datagridview不加载滚动条行为怪异。这里是我的代码螺纹C#填入datagridview的

delegate void CambiarProgresoDelegado(); 

按钮单击

private void btn_busca_Click(object sender, EventArgs e) 
    { 
     pictureBox1.Visible = true; 
     thread= new Thread(new ThreadStart(ejecuta_sql)); 
     thread.Start(); 
    } 

方法

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; 


     } 

和.gif文件冻结,直到该线程完成他的工作。

回答

1

您创建一个线程,但随后立即与调用()使代码切换回主UI线程,否定使得线程在首位的任何好处。

运行其他线程的查询,然后调用()仅仅是一部分更新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; 
     }); 
    } 
+0

谢谢!!像魅力一样工作,所以我只使用Invoke来更新主线程的UI? – user2615105

+0

这是正确的。 “工作”是在您创建的线程上完成的,只有UI_的_updates被调用,导致它们在主UI线程上运行。 –

2

您可以考虑改变你的做法,特别是如果你是从做了很多GUI更新的你后台线程。原因:

  • UI更新需要时间,因为你必须锁定
  • 太多的更新从后台线程未来将压倒UI,并可能导致冻结它会减慢后台处理。
  • 你可能不希望更新GUI每毫秒左右

我宁愿是做投票站后台线程数据,而不是。将GUI定时器设置为300ms,然后检查是否有任何数据可以更新,然后通过适当的锁定进行快速更新。

下面是代码示例:

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; 
     } 
    } 

注意,虽然文本变量更新非常频繁的GUI仍然停留响应。相反,如果更新每个“文本”更改的GUI,系统将冻结。

+0

以及解释,它可以帮助你如何显示实际的代码示例/片段! – AADProgramming

+0

添加代码示例。不能编辑我的帖子。 –