2017-03-22 20 views
0

私はParallel.Forループ内のOracleデータベースにアクセスしたいコードに取り組んでいます。ループは数分間実行され、エラーが発生します。C#Parallel.ForとOracleデータベースアクセス - メモリ例外

"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

内部例外はありません。私の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オブジェクトの内部から来ているようだから完全に理解できません。データベース接続はスレッドセーフではありませんか?接続プールを使用するために接続文字列を変更しようとしましたが、何も変更されませんでした。

答えて

2

メモリの問題は、です。間違ったリソースの使用により、常にが発生します。ループ終了後、接続を適切に解放しません。あなたはIDisposableインタフェースを実装する必要があり、その後、あなたがusing keywordと、このような方法で、あなたのコードを書き換える必要

// 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 
    } 
} 
+0

はどのように不正なメモリのアクセスを引き起こす以前のリソースを配置していないでしょうか?メモリが長い間有効であるので、disposeを持たないものがあればこのようなバグを隠すでしょう。 – Voo

+0

@Voo OPはいくつかの**の後にメモリエラー**を満たすため、管理されていないリソースが単にメモリ破損につながります – VMAtm

+0

解放されたメモリは解放されたメモリにアクセスしません。管理されていないリソースを処分しないとリソースがなくなり、アクセスエラーは発生しません(メモリが不足し、アンマネージコードがmallocとcoの戻り値をチェックしない場合を除く) – Voo

関連する問題