【问题标题】:Catching Exceptions from an Event Handler from another class从另一个类的事件处理程序中捕获异常
【发布时间】:2016-05-19 13:33:36
【问题描述】:

我有来自 A 类的以下 sn-p,我在其中对数据库执行异步操作并订阅 InfoMessage 事件处理程序以捕获来自 SQL 的信息性消息。

public void BackupDatabase(string DatabaseName, string BackupLocation, bool backupType = true)
    {
        //SQL for FULL database backup
        string SQL = "BACKUP DATABASE [" + DatabaseName + "] TO  DISK = N'" + BackupLocation + "\\" + DatabaseName +".bak' WITH FORMAT,  NAME = N'" + DatabaseName + "-Full Database Backup', STATS = 1";

        using (SqlConnection db_conn = new SqlConnection(ConnectionString))
        {

            UpdateStatusText("Establishing Connection to Database");
            db_conn.Open();
            db_conn.FireInfoMessageEventOnUserErrors = true;
            db_conn.InfoMessage += BackupInfoMessages;

            using (SqlCommand sqlCmd = new SqlCommand(SQL, db_conn))
            {

                sqlCmd.ExecuteNonQuery();

            }
            UpdateStatusText("Backup Complete.");
        }
    }

    private void BackupInfoMessages(object sender, SqlInfoMessageEventArgs e)
    {
        foreach (SqlError info in e.Errors)
        {
            if(info.Class > 10)
            {
                logFile.ExMsg("Exception : " + e.Message);
                throw new Exception(e.Message);

            }
            else
            {
                UpdateStatusText(e.Message, 1);
            }
        }
    }

在 B 类中,我使用了一个后台工作程序,它使用 A 类的实例在 try catch 中运行“BackupDatabase”

try 
{
   DBOperations.BackupDatabase("DB","C:\\DBBackup\\DB.bak");
}
catch (Exception ex)
{

  logFile.ExMsg(ex.Message);
  logFile.ExMsg(ex.StackTrace);
  /* additional code to stop bgWorker */

 }

根据从 SQL 报告的消息的严重性级别,我将相应地处理它,每当从那里抛出异常时,BackgroundWorker 都没有捕获从 ClassA.BackupInfoMessages 抛出的异常......我已经尝试过移动我的try/catch 块并在 BackupDatabase 方法中添加一个没有运气。它似乎只是跳过它并将其视为没有抛出异常。 VS 中的调试器显示抛出了 System.Exception,但没有任何影响。我错过了什么或做错了什么?谢谢!

【问题讨论】:

  • 我转而使用 ExecuteNonQuery()。感谢您的帮助!
  • 我删除了我的答案,因为调用代码确实应该捕获到异常。你在 VS 中看到它,但它没有被调用方法捕获,这很奇怪......必须考虑一下:-|
  • 您可能会尝试的一件事是不在后台工作人员中捕获异常,而是在工作人员的 RunWorkerCompleted 事件中处理它。由于有多个线程在运行,这可能是捕获它的更合适的方法。
  • 我将如何在RunWorkerCompleted 事件中处理它?删除 try/catch 块什么都不做,并且仍然像正常运行一样返回,尽管调试器显示抛出异常。

标签: c# .net exception-handling


【解决方案1】:

您需要将 BackupInfoMessages 视为在其自己的单独后台工作程序中运行,这就是 try/catch 捕获它的原因,因为该事件与您的 try/catch 块不在同一个调用堆栈中。

除了直接引发异常外,您还需要其他方式来传达发生了错误。

我认为,但不是 100% 肯定,任何 11 级或更高级别的错误都会使 ExecuteNonQuery 抛出带有错误信息的异常,因此您可能不需要在事件处理程序中手动引发异常。但是设置 .FireInfoMessageEventOnUserErrors = true 可能会改变这种行为。

【讨论】:

  • 我不知道一种很好的替代方法来显示我头顶的错误信息,但如果我想到一个我会用一个例子更新我的答案。
  • 你是对的,将.FireInfoMessageEventOnuserErrors 设置为 false(或删除它)会引发异常并部分解决我的问题。另一方面,如果没有从 SQL 发送 InfoMessage,我无法向用户报告备份进度。
  • 我只是简单地分配一个公共布尔值来检查进程是否失败,并根据 SQL 消息的严重级别进行测试并相应地切换布尔值,然后在查询完成后测试布尔值,最后抛出一个BackupDatabase 的异常取决于结果。
  • @ephtee 你考虑过using SMO to do the backup operation吗?它有一个您可以收听的PercentComplete 事件。
  • 我已经调查过了,但是运行程序的目标机器是否需要任何先决条件才能运行命令?比如预装了Management Studio?
猜你喜欢
  • 1970-01-01
  • 2013-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多