【问题标题】:How to handle InvalidOperationException inside a catch block如何在 catch 块中处理 InvalidOperationException
【发布时间】:2014-07-17 17:32:04
【问题描述】:

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

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

当我调用 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”它创建于。

【问题讨论】:

  • 是的,格兰特。我不确定为什么我被指责没有阅读异常,或者为什么有人会评论只是告诉我我需要修复错误。显然我知道,但无法弄清楚这就是我在这里的原因。异常内容为“System.Windows.Forms.dll 中发生‘System.InvalidOperationException’类型的异常,但未在用户代码中处理附加信息:跨线程操作无效:控件‘ProgressForm’从除创建它的线程。”所以也许我不能在 backgroundWorker1 方法中调用 .Close() ?应该在哪里?
  • 让自己熟悉 UI 线程和后台线程的区别。在进行 GUI 编程时了解这一点至关重要。 google.com/… 这应该让你开始。
  • 里面肯定有一些有价值的资源,谢谢。我只用了几个月的 C# 编程,这是我的第一个线程项目。简单的初学者错误,所以我很感激输入。

标签: c# exception asynchronous try-catch backgroundworker


【解决方案1】:

您不能在DoWork 事件中直接接触 UI 线程,包括关闭您在运行线程之前创建的(我假设)您创建的表单。这里有一个基本的“流程”供您遵循:

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

  2. 启动 BackgroundWorker。

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

  4. RunWorkerCompleted 事件中检查e.Error...如果不是null,则存在异常,您可以采取适当的措施,例如通知用户。因为这个事件又回到了 UI 线程,你也可以关闭你的表单。

试试这个:(即时编写,应该进行一些调整)

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
    ...
}

【讨论】:

  • 感谢您的解释。它帮助我发现被抛出的异常(我是为了测试而做的)可以在其他地方处理,进而改进了我的代码,因为我能够从一个 excel 文件移动到下一个,即使第一个文件没有不行。我知道,Try/Catch 块很讨厌,但对于 IO 来说,这似乎是最好的选择。无论如何,感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2019-11-12
  • 2017-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-15
  • 1970-01-01
相关资源
最近更新 更多