例外:跨线程操作无效:控制'pgImportProcess(进度条)'从一个线程访问,而不是它在[重复]上创建的线程

Posted

技术标签:

【中文标题】例外:跨线程操作无效:控制\'pgImportProcess(进度条)\'从一个线程访问,而不是它在[重复]上创建的线程【英文标题】:Exception : Cross-thread operation not valid: Control 'pgImportProcess(Progress Bar)' accessed from a thread other than the thread it was created on [duplicate]例外:跨线程操作无效:控制'pgImportProcess(进度条)'从一个线程访问,而不是它在[重复]上创建的线程 【发布时间】:2012-01-24 02:59:43 【问题描述】:

可能重复:Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on

如何纠正这个异常:

Cross-thread operation not valid: Control 'pgImportProcess(ProgressBar control)' accessed from a thread other than the thread it was created on.

代码:

表格:

private void btnImport_Click(object sender, EventArgs e)


        if (CheckDataValidation() == false) return;

        if (MessageBox.Show("Do you want to import this file?", "Import", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) return;
        Cursor.Current = Cursors.WaitCursor;
        //_blacklist.Process(pgImportProcess);

        Thread thread = new Thread(new ThreadStart(delegate  _blacklist.Process(pgImportProcess); ));
        thread.Start();

        if (!thread.IsAlive) thread.Abort();

        //ThreadStart process = delegate
        //                                
        //                                    _blacklist.Process(pgImportProcess);
        //                                ;
        //Thread threadProcess = new Thread(process);
        //threadProcess.Start();

        //if(!threadProcess.IsAlive) threadProcess.Abort();

    

类:

public void Process(ProgressBar process)


        int same = 0, added = 0, updated = 0;

        OracleConnection connection = (OracleConnection)DbConnection.Instance();
        OracleTransaction transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted);

        process.Step = 1;
        process.Minimum = 1;
        process.Maximum = _recordNumber;



        while (_csv.ReadNextRecord())
        
            if (_csv[0] == null | _csv[0] == "") break;

            process.PerformStep();

            using (OracleCommand cmd = new OracleCommand(_sql, connection))
            
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.CommandTimeout = 600;
                cmd.BindByName = true;

                switch (_fieldCount)
                
                    case SdnName :
                        ImportBlacklistName(cmd);
                        break;
                    case SdnAddress:
                        ImportBlacklistAddress(cmd);
                        break;
                    case SdnAlt :
                        ImportBlacklistAlt(cmd);
                        break;
                

                try
                
                    cmd.ExecuteNonQuery();


                    switch (cmd.Parameters["message_out"].Value.ToString())
                    
                        case "Added":
                            added += 1;
                            break;
                        case "Same":
                            same += 1;
                            break;
                        case "Updated":
                            updated += 1;
                            break;
                    
                
                catch (Exception error)
                
                    transaction.Rollback();
                    MessageBox.Show(error.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                
            
        
        transaction.Commit();
        MessageBox.Show(String.Format("Total Record : 0 ; Added : 1 ; Updated : 2 ; Same : 3 !!!!",_recordNumber,added,updated,same), "Import successsfull", MessageBoxButtons.OK, MessageBoxIcon.Information);
        _recordNumber = 0;
        process.Value = 1;
        _csv.Dispose();
    

它在 Process.step = 1

时捕获异常

如何解决这个问题?提前致谢

【问题讨论】:

请在尝试发布新问题时查找相关问题。那么你会发现其中一些问题:1、2、3 【参考方案1】:

您无法从不同的线程更新用户界面(如错误所示)。

您需要调用该方法。任何简单的方法都是通过MethodInvoker:

        process.Parent.Invoke((MethodInvoker)delegate
        
            process.Step = 1;
            process.Minimum = 1;
            process.Maximum = _recordNumber;
        );

在您尝试更新进度条中的属性时,您将需要使用此代码。

【讨论】:

【参考方案2】:

您需要将 BeginInvoke 与委托一起使用,例如:

MethodInvoker yourAction = delegate
      process.Step = 1;
    process.Minimum = 1;
    process.Maximum = _recordNumber; ;
process.BeginInvoke(yourAction);

【讨论】:

【参考方案3】:

您需要使用 Dispatcher 才能进入 UI 的线程。

如果你使用 WPF:

Dispatcher.BeginInvoke(new Action(()=>

    //place code here
));

【讨论】:

我没有使用 WPF ,只是使用 windows 应用程序表单 (WAF)

以上是关于例外:跨线程操作无效:控制'pgImportProcess(进度条)'从一个线程访问,而不是它在[重复]上创建的线程的主要内容,如果未能解决你的问题,请参考以下文章

跨线程Winforms控件编辑[重复]

跨线程操作无效[重复]

获取跨线程操作无效[重复]

为啥我没有收到“跨线程操作无效”错误

跨线程操作无效:控件“statusStrip”从创建它的线程以外的线程访问

跨线程操作无效:控件'listBox1'从一个>线程访问,而不是它在[重复]上创建的线程