2010-06-15 49 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