2015-01-07 30 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

添加代碼示例。不能編輯我的帖子。 –