0

我正在处理一些我想在Parallel.For循环内访问 Oracle 数据库的代码。循环将运行几分钟,然后导致错误:

“试图读取或写入受保护的内存。这通常表明其他内存已损坏。”

没有内在的例外。在我的Parallel.For循环中,我正在创建一个打开数据库连接作为本地对象。我的代码如下所示:

static void CheckSinglePath(Path p)
{    
     string sqlBase = "select * from table where hour = #HOUR#";
     Parallel.For (1, 24, i =>
     {        
            DBManager localdbm = new DBManager();                
            string sql = sqlBase;
            sql = sql.Replace("#HOUR#", i.ToString());
            OracleDataReader reader = db.GetData(sql);
            if (reader.Read())
            {
               //do some stuff
            }
            reader.Close();
     });
}

class DBManager
{
    OracleConnection conn;
    OracleCommand cmd;
    public DBManager()
    {
        string connStr = "blahblahblah;Connection Timeout=600;";
        conn = new OracleConnection(connStr);            
        conn.Open();
        cmd = conn.CreateCommand();
    }

    public OracleDataReader GetData(string sql)
    {
        cmd.CommandText = sql;
        return cmd.ExecuteReader();//EXCEPTION HERE!
    }        
}

我究竟做错了什么?如何创建 24 个并行 Oracle 连接来处理数据?我猜这里发生了某种竞争条件或内存泄漏,我不完全理解,因为它似乎来自OracleConnection对象内部。数据库连接不是线程安全的吗?我尝试更改连接字符串以使用连接池,但这并没有改变任何东西。

4

1 回答 1

2

内存问题总是由错误的资源使用引起的。循环退出后,您没有正确释放连接。

您需要实现接口,然后您需要使用关键字IDisposable以这种方式重写您的代码:using

// dispose the connection after command finished
using (var localdbm = new DBManager())
{            
    var sql = sqlBase;
    sql = sql.Replace("#HOUR#", i.ToString());
    using (var reader = db.GetData(sql))
    {
        if (reader.Read())
        {
           //do some stuff
        }
        // no need to close reader
        // as it's being disposed inside using directive
    }
}
于 2017-03-22T22:35:03.060 回答