代码之家  ›  专栏  ›  技术社区  ›  Sean Hanley

如何从XSD生成的类型化数据集中捕获连接超时异常?

  •  0
  • Sean Hanley  · 技术社区  · 16 年前

    我有一个Windows窗体应用程序。它通过XSD设计器使用强类型数据集。我通过异步线程运行数据访问查询,执行方式如下:

    // Calling it in code on the main thread:
    LoadDataList_WorkerCaller dataDelegate = new LoadDataList_WorkerCaller(LoadDataList_Worker);
    IAsyncResult iar = default(IAsyncResult);
    iar = dataDelegate.BeginInvoke(LoadDataList_Complete, null);
    
    // How they are defined in the class:
    private delegate TypedDataSets.DataListDataTable LoadDataList_WorkerCaller();
    private TypedDataSets.DataListDataTable LoadDataList_Worker()
    {
        // ...blah blah
        try
        {
            DataListTableAdapter adapter = new DataListTableAdapter();
            TypedDataSets.DataListDataTable dataList = adapter.GetList(); // causes connection attempt
        }
        catch (SqlException sqlex)
        {
            // Log DB error and notify user of problem
        }
    
        return dataList;
    }
    private delegate void LoadDataList_CompleteCaller(IAsyncResult iar);
    private void LoadDataList_Complete(IAsyncResult iar)
    {
        if (InvokeRequired)
        {
            LoadDataList_CompleteCaller invokeDelegate = new LoadDataList_CompleteCaller(LoadDataList_Complete);
            Invoke(invokeDelegate, new object[] { iar });
            return;
        }
    
        // Downcast the IAsyncResult to an AsyncResult -- it's safe and provides extra methods
        System.Runtime.Remoting.Messaging.AsyncResult ar = (System.Runtime.Remoting.Messaging.AsyncResult)iar;
    
        LoadDataList_WorkerCaller dataDelegate = (LoadDataList_WorkerCaller)ar.AsyncDelegate;
        TypedDataSets.DataListDataTable dataList = null;
    
        try
        {
            dataList = dataDelegate.EndInvoke(iar);
        }
        catch (Exception ex)
        {
            // Final fail-safe, for non-DB exceptions; we'll log 'em and such here
        }
    
        // ... use dataList object as normal
    }
    

    我将多线程部分基于中的建议 this SO question

    如果我故意损坏连接字符串,导致连接尝试失败,那么在.NET framework代码区的某个地方会生成一系列大约10个SQLException并捕获(第一次机会异常)。之后,应用程序抛出一个未处理的异常并终止程序。我之所以知道这一点,是因为我在主方法上有一个最后的机会异常捕获器,如果有什么东西一直冒泡,它会记录它们。但我的try-catch-in-worker和回调函数(如上所述)从未被触发。他们好像完全被忽略了?即使开始出现问题的那一行在try-catch块中。

    信息技术 SqlException,因此应该捕获它,但是Main方法上的try catch会捕获TargetInvocationException(SqlException作为InnerException)。错误如预期所示:

    建立与SQL Server的连接时发生与网络相关或特定于实例的错误。找不到服务器或无法访问服务器。验证实例名称是否正确,以及SQL Server是否配置为允许远程连接(提供程序:TCP提供程序,错误:0-无法建立连接,因为目标计算机主动拒绝了它。)

    但是为什么我的try-catch错过了它,而我却得到了一个Targeting异常?有什么好处?我明白这是因为异常发生在主UI线程之外的一个单独线程上,但是如果生成的异常是在我尝试捕获的代码中的这个单独线程中生成的,为什么它会忽略它,而完全在线程上释放,然后导致主线程死机并中止?

    可以 在那里完全处理它,从而停止异常的运行。。。要是我的试捕真能抓住它就好了!

    1 回复  |  直到 9 年前
        1
  •  0
  •   Paul Keister    16 年前

    在我看来,问题出在您发布的代码之外。如果我们假设所讨论的数据集使用的是SqlClient,并且您试图捕获的异常的完全限定类型是System.Data.SqlClient.SqlException,那么代码应该完全按照您的预期工作。对此问题的一种可能解释是,类型化数据集使用System.Data.OleDb而不是System.Data.SqlClient。

    另一个良好的健全性检查是完全限定SqlException的类型(System.Data SqlClient.SqlException)。在您的代码库中,可能有人声明了另一个名为SqlException的类,该类隐藏了真正的McCoy。