2010-06-15 36 views
2

我嘗試啓動多線程,但我不能它返回給我錯誤:跨線程操作無效:'listBox1'線程被創建用來控制來自另一線程的外部訪問。如何解決「跨線程操作無效」?

MyCodes:


    public DataTable dTable; 
     public DataTable dtRowsCount; 
     Thread t1; 
     ThreadStart ts1; 
    void ExcelToSql() 
     { 
      // SelectDataFromExcel(); 
      ts1 = new ThreadStart(SelectDataFromExcel); 
      t1 = new Thread(ts1); 
      t1.Start(); 
     }
void SelectDataFromExcel() 
     { 
      string connectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Source\Addresses.xlsx;Extended Properties=""Excel 12.0;HDR=YES;"""; 
      OleDbConnection excelConnection = new OleDbConnection(connectionString); 
         string[] Sheets = new string[] { "Sayfa1"}; 
      excelConnection.Open(); // This code will open excel file.    
      OleDbCommand dbCommand; 
      OleDbDataAdapter dataAdapter; 
      // progressBar1.Minimum = 1; 

      foreach (var sheet in Sheets) 
      { 
       dbCommand = new OleDbCommand("select * From[" + sheet + "$]", excelConnection); 
       //progressBar1.Maximum = CountRowsExcel(sheet).Rows.Count; 
       // progressBar2.Value = i + 1; 
       System.Threading.Thread.Sleep(1000); 
       **listBox1.Items.Add("Tablo ismi: "+sheet.ToUpper()+"Satır Adeti: "+CountRowsExcel(sheet).Rows.Count.ToString()+" ");** 
       dataAdapter = new OleDbDataAdapter(dbCommand); 
       dTable = new DataTable(); 
       dataAdapter.Fill(dTable); 
       dTable.TableName = sheet.ToUpper(); 
       dTable.Dispose(); 
       dataAdapter.Dispose(); 
       dbCommand.Dispose(); 
       ArrangedDataList(dTable); 
       FillSqlTable(dTable, dTable.TableName); 
      } 

      excelConnection.Close(); 
      excelConnection.Dispose(); 
     }

回答

3

您無法更新從非UI線程的UI組件。使用TaskScheduler.FromCurrentSynchronizationContext編組對UI線程的調用。

+1

你學習常用的東西,我絕對喜歡約SO。他們已經偷偷吃了一些好吃的東西,而不是他們。 – Spence 2010-06-15 14:20:00

4

在UI線程中創建的控件無法以其他線程以正常方式訪問。請創建一個委託並使用control.Invoke調用委託。

下面提供的方法的示例可以用於使上的按鈕能見度不管你在線程上下文的。

private void EnableButtonVisibility(Button btn, bool enable)  
{  
    if (!btn.InvokeRequired)  
    {  
btn.Visible = enable;  
    } 
    else  
    {  
     btn.Invoke(new EnableButtonVisibilityHandler(EnableButtonVisibility), btn, enable);  
    }  
}  
delegate void EnableButtonVisibilityHandler(Button btn, bool enable); 
+0

這是我偶爾會使用的解決方案。 – Meiscooldude 2010-06-15 14:18:17

+2

不需要創建一個委託,你可以使用基類庫中可用的'Action '。 – 2010-06-15 14:22:16

+0

+1是的。這也可以用來添加內聯方法。 – 2010-06-15 14:23:46

5

在背景線程不允許訪問UI組件。

在多線程的形式,我有這樣的代碼:

private delegate void InvokeAction(); 
    private void DoUI(InvokeAction call) { 
     if (IsDisposed) { 
      return; 
     } 
     if (InvokeRequired) { 
      try { 
       Invoke(call); 
      } catch (InvalidOperationException) { 
       // Handle error 
      } 
     } else { 
      call(); 
     } 
    } 

然後從我的後臺線程我可以像這樣的代碼:

// Stuff in other thread 
    myVar = GetFromDb(); 
    DoUI(() => { 
     // Access UI components here 
     listBox1.Items.Add(myVar); 
    }); 
    // More other thread 
+1

trippple點,如果我可以獎勵這個答案..可重複使用的代碼是前進的方向! – Christian 2011-11-05 19:15:39