实现多线程后,与数据库的连接丢失

时间:2016-10-29 21:37:16

标签: c# multithreading

我的应用正在使用HTMLAgilityPack来解析HTMLSystem.Data.SqlClient以连接本地数据库并获取/插入数据。

问题是代码示例没有任何错误:

Database databaseObject = new Database();
List<Account> accounts = new List<Account>();
...
//Add some data to accounts and databaseObject 
...
    databaseObject.Open()
    foreach (Account account in accounts)
    {
        accounts.doMagic(this, databaseObject);
    }

我没有添加databaseObject.Close()以确保与数据库的连接存在。好吧,现在这里的代码不能正常运行:

Database databaseObject = new Database();
List<Account> accounts = new List<Account>();
...
//Add some data to accounts and databaseObject 
...
    databaseObject.Open()
    foreach (Account account in accounts)
    {
        Thread thread = new Thread(() => account.doMagic(this, databaseObject ));
        thread.Start();
    }

这也行不通:

Database databaseObject = new Database();
List<Account> accounts = new List<Account>();
...
//Add some data to accounts and databaseObject 
...
    databaseObject.Open()
        Parallel.ForEach(accounts, account =>
            {
                account.doMagic(this, databaseObject );
            });

它开始有效,但几秒钟后我收到System.InvalidOperationException需要ExecuteNonQuery需要打开和可用连接的信息。

什么?连接应该一直打开!

我获得System.Data.SqlClient.SqlException的更多信息Timeout Expired

到底是怎么回事?我没有关闭任何连接,所以它怎么能关闭?我无法理解为什么它不能正常实现多线程...

1 个答案:

答案 0 :(得分:1)

SQLConnection不是纯托管类,而只是一个包装器。实际连接是COM对象,具有COM线程模型的所有限制。尝试回答这个简单的问题:如果你使用来自不同线程的单个连接,你可以在什么线程中捕获它的异常?

好消息是:您可以在相同或不同的线程中打开和关闭连接而不会因为连接池而丢失性能(实际上连接池可以保持连接打开)。此外,连接池尝试解决许可证限制(当前打开的连接的限制)和一些其他问题。

坏消息是:使用多个连接时,如果遇到服务器问题,您将面临大量错误。对于这样的体系结构,服务器连接管理不是一个简单的案例。对于许多场景,最可靠的方法是实现数据适配器单例来封装所有与客户端数据库相关的逻辑。