【问题标题】:How can solve "Cross-thread operation not valid"?如何解决“跨线程操作无效”?
【发布时间】:2010-06-15 14:09:08
【问题描述】:

我尝试启动多线程但我不能它返回给我错误:跨线程操作无效:'listBox1'线程被创建以控制来自另一个线程的外部访问。

我的代码:

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

【问题讨论】:

    标签: c# .net visual-studio multithreading excel


    【解决方案1】:

    后台线程不允许访问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 
    

    【讨论】:

    • 三倍积分如果我可以为这个答案奖励它。可重用的代码是前进的方向!
    【解决方案2】:

    在 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);
    

    【讨论】:

    • 这是我偶尔会使用的解决方案。
    • 无需创建委托,可以使用基类库中提供的Action<Button, bool, bool>
    【解决方案3】:

    您无法从非 UI 线程更新 UI 组件。使用TaskScheduler.FromCurrentSynchronizationContext 将调用编组到 UI 线程。

    【讨论】:

    • 你每天都会学到一些东西,我非常喜欢 SO。他们已经把一些好东西偷偷带进了 4.0,不是吗。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多