如何在catch块中处理InvalidOperationException

时间:2014-07-17 17:32:04

标签: c# exception asynchronous try-catch backgroundworker

我的代码使用BackgroundWorker从Excel工作表中读取信息并将其上传到数据库,同时还显示一个表单,通知用户进度。这是一个C#项目。

但是,在我的try / catch语句中读取excel文件并上传它们,我希望能够关闭进度表单,因为它不再有用。

当我调用BackgroundWorker类的.Close()方法时,会触发InvalidOperationException,我不知道如何处理这种情况。有办法处理吗?还有另一种关闭窗户的方法吗?

这是我的catch块(位于DoWork事件中):

catch (Exception ex)
{
    MessageBox.Show("Error Uploading Data. See log for details.", "Database Submission Error", MessageBoxButtons.OK);
    // Cancel operation
    backgroundWorker1.CancelAsync();
    // Close form
    progress.Close();
}

backgroundWorker1是BackgroundWorker读取/上传数据,progress是显示进度条和计数完成/剩余信息的窗口。

例外:

  

System.Windows.Forms.dll中发生了'System.InvalidOperationException'类型的异常但未在用户代码中处理附加信息:跨线程操作无效:从线程以外的线程访问控制'ProgressForm'它创建于。

1 个答案:

答案 0 :(得分:2)

您无法在直接触及UI线程的DoWork事件中执行任何操作,包括在运行线程之前关闭您创建的表单(我假设)。这是一个基本的"流程"你可以跟随:

  1. 创建进度表单的新实例并显示它。

  2. 启动BackgroundWorker。

  3. 不要在DoWork事件中捕获异常,除非您打算纠正导致它们发生的情况。否则,异常将停止工作并进入RunWorkerCompleted事件,该事件发生在UI线程上。

  4. 检查e.Error活动中的RunWorkerCompleted ...如果它不是null,那么会有异常,您可以采取适当的措施例如通知用户。由于此事件已返回UI线程,因此您也可以关闭表单。

  5. 试试这个:(即时编写,应该通过一些调整进行编译)

    var progress = new MyProgressForm();
    progress.Show();
    
    backgroundWorker1.RunWorkerAsync();
    
    ...
    ...
    
    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error != null)
        {
            // log the exception
    
            MessageBox.Show("Error Uploading Data. See log for details.",
                            "Database Submission Error", MessageBoxButtons.OK);
    
            // we're back on the UI thread, so we can touch UI elements
            progress.Close();
    
            return;
        }
    
        // stuff to do if no error occurred
        ...
    }