【问题标题】:C# SqlClient connection open in thread - SqlException not caughtC# SqlClient 连接在线程中打开 - SqlException 未捕获
【发布时间】:2014-08-01 07:20:23
【问题描述】:

我已经实现了SqlClient 带有超时参数的连接功能。这意味着,connection.open() 在另一个线程中,并且在线程启动后,我正在检查经过的时间。如果时间已达到超时,则线程被中止并且不建立连接。

问题是,如果我的超时时间大于默认的connection.open() 超时时间,open() 会抛出SqlException,这不会在我的Catch(SqlException) 块中捕获。

我正在另一个线程中开始整个连接过程:

public void connect()
{
    Thread connectThread = new Thread(waitForTimeout);
    connectThread.Start();
}

连接线程 -> 启动另一个线程等待超时

public void waitForTimeout()
{
    connection = new SqlConnection(connectString);

    Thread timeoutThread = new Thread(openConnection);
    timeoutThread.Start();

    DateTime quitTime = DateTime.Now.AddMilliseconds(timeout);
    while (DateTime.Now < quitTime)
    {
        if (connection.State == ConnectionState.Open)
        {
            transac = connection.BeginTransaction();
            command = connection.CreateCommand();
            command.Transaction = transac;
            break;
        }
    }

    if (connection.State != ConnectionState.Open)
        timeoutThread.Interrupt();
}

这里的异常在 open() 默认超时后没有被捕获:

private void openConnection()
{
    try
    {
        connection.Open();
    }
    catch(SqlException ex)
    {
        // This isn't caught anytime
    }
}

感谢您的任何想法!

【问题讨论】:

  • 这是一个糟糕的模式。 SqlConnection 支持开箱即用的连接超时设置,您为什么要尝试以复杂且不起作用的方式做同样的事情?没有办法中止不在托管代码中的线程(甚至在托管代码中中止也是非常不受欢迎的)。更不用说Interrupt 没有做你认为它做的事情。并且在一段时间内旋转 cpu 也是等待连接打开的一种愚蠢方式。 SqlConnection 甚至是线程安全的吗?我不这么认为...
  • SqlConnection 肯定不是线程安全的。跨线程共享它是一个非常糟糕的主意,并且肯定会给您带来麻烦。稍微偏离主题:使用 Tasks API 而不是直接使用线程。对于大多数用例而言,直接使用低级线程 API 已过时。
  • 说真的,在一个问题上投入更多的线程很少有帮助。学习如何正确使用SqlConnection,使用异步方法,了解多线程如何工作以及如何使用信号,处理同步等。多线程是一个非常复杂和复杂的问题,不是一个简单的解决方案阻塞问题。
  • 我尝试将超时添加到连接字符串,但它不起作用。当然,我一直在寻找一些更清洁的解决方案。 Task 也是问题,因为我应该让它与 .NET 3.5 一起使用。即使SqlConnection 中的超时有效,由于连接时应用程序冻结,我需要在另一个线程中运行。

标签: c# sql-server multithreading sqlconnection sqlexception


【解决方案1】:

它是不是被抓住了,还是没有被扔掉? Thread.start 只安排线程运行,但并不意味着它会立即启动。也许代码一直运行到 threadTimeout 中断,然后 openConnection 启动并始终在默认超时内成功打开连接。

---编辑

在这种情况下,你可以尝试:

  1. SqlException 替换为 Exception 并检查是否捕获到诸如 ThreadInterruptedException 之类的内容

  2. 将 openConnection 方法的内容放在你的 waitForTimeout 方法中 connection = new SqlConnection(connectString); 之后(并注释其余代码),看看是否仍然没有处理异常。如果没有,那就放到connect()方法里再检查一遍。

【讨论】:

  • 不,我肯定已经停止了 sql server。 connection.open() 一段时间后抛出 SqlException,但它没有在我的 catch 块中捕获,因此未处理。
  • 是的,我尝试在没有线程的情况下运行,也尝试捕获异常,但也没有效果。现在我注意到它与调试器中的异常设置有关。如果我在异常列表中取消选中“抛出”选项(在 Visual Studio 中为 CTRL + D + E),我终于能够捕获异常!
【解决方案2】:

在 cmets 之后,我尝试实施新的解决方案,结果如下:

构造函数:

/* ------------------------------------------------------------------------- */
public Database(string source, string database, string user, string password,
    int timeout, DelegateConnectionResult connectResult)
{
    this.timeout = timeout;
    this.connectResult = connectResult;

    connectString = "server=" + source +
          ";database=" + database +
          ";uid=" + user + 
          ";pwd=" + password + 
          ";connect timeout=" + Convert.ToInt16(timeout / 1000);
}

异步连接:

/* ------------------------------------------------------------------------- */
public void connectAsync()
{
    connectThread = new Thread(connectSync);
    connectThread.Start();
}

同步连接:

/* ------------------------------------------------------------------------- */
public void connectSync()
{
    connection = new SqlConnection(connectString);

    try
    {
        connection.Open();
        transac = connection.BeginTransaction();
        command = connection.CreateCommand();
        command.Transaction = transac;

        if (connection.State == ConnectionState.Open)
            connectResult(true);
        else
            connectResult(false);
    }
    catch
    {
        connectResult(false);
    }
}

我从这篇文章中找到了原始问题女巫 SqlException 的解决方案:它与 Visual Studio 调试器中的异常设置有关。如果我在异常列表中取消选中“抛出”选项(在 Visual Studio 中为 CTRL + D + E),我终于能够捕获异常。

【讨论】:

    猜你喜欢
    • 2016-02-03
    • 2021-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-25
    • 2016-06-21
    相关资源
    最近更新 更多