2016-06-28 8 views
-1

一部のリストのブロッキングコレクションがあり、それをタスクで処理します。ブロッキングコレクションのデータをデータベースに追加します。ここで は、コードの一部です:DatabaseClassからブロッキングコレクションが何らかの理由で処理を停止する

private static Task _databaseTask; 
private static readonly BlockingCollection<List<SomeItem>> DataToBeInsertedToDatabase = new BlockingCollection<List<SomeItem>>(); 
public static void ProcessInsertsCollection() 
{ 
    _databaseTask = Task.Factory.StartNew(() => 
    { 
     foreach (List<SomeItem> data in DataToBeInsertedToDatabase.GetConsumingEnumerable()) 
     { 
      try 
      { 
       DateTime[] dateTimes = data.Select(d => d.ContributionDateTime).ToArray(); 
       string[] values = data.Select(d => d.Value).ToArray(); 
       string[] someOtherValues = data.Select(d => d.SomeOtherValues).ToArray(); 
       Program.IncrementDatabaseRecordsRegistered(data.Count); 
       DatabaseClass.InsertValues(dateTimes, values, someOtherValues); 
      } 
      catch (Exception ex) 
      { 
       //log the error 
      } 
     } 
    }); 
} 

機能:

public static bool InsertValues(DateTime[] dateTimes, string[] values, string[] someOtherValues) 
{ 
    if (!IsConnected()) 
    { 
     Connect(); 
    } 
    var rowsInserted = 0; 
    try 
    { 
     using (OracleCommand command = _connection.CreateCommand()) 
     { 
      command.CommandText = 
       string.Format(
        "Insert into {0} (*****) VALUES (:1, :2, :3)", 
        _tableName); 
      command.Parameters.Add(new OracleParameter("1", 
       OracleDbType.Date, 
       dateTimes, 
       ParameterDirection.Input)); 
      command.Parameters.Add(new OracleParameter("2", 
       OracleDbType.Varchar2, 
       values, 
       ParameterDirection.Input)); 
      command.Parameters.Add(new OracleParameter("3", 
       OracleDbType.Varchar2, 
       someOtherValues, 
       ParameterDirection.Input)); 

      command.ArrayBindCount = dateTimes.Length; 
      rowsInserted = command.ExecuteNonQuery(); 
     } 
    } 
    catch (Exception ex) 
    { 
     //log the error 
    } 
    return rowsInserted != 0; 
} 

問題は、アプリケーションの作業データの数時間後にまだ処理コレクションをブロックではなくに追加されていることです。私はそれをデバッグするとき、それはタスク内の任意のブレークポイントで停止しません。変数_databaseTaskをチェックすると、そのタスクが実行中であることが示されます。 _connection変数は、データベースが接続されていることを示します。私はtry/catchをforeachとInsertValues関数に追加しましたが、それは助けになりませんでした。私は最初にこの仕事がGCによって集められたと思ったので、すべて静的にしました。しかし、そうではありませんでした。

私のアプリケーションでは、別のブロッキングコレクションがあり、タスク内での処理は問題なく動作するため、問題はおそらくデータベースの呼び出しと関連しています。私はデータベース機能を呼び出すことはありません。

数時間後にコレクションが消費されない理由を知りたい人はいらっしゃいますか?

編集: 質問が理解できないときは、投票しないでください。ソリューションを知っている人が私の質問を見る可能性は低くなります。 私はこの問題について多くの研究をしました。

今日私は、おそらくスレッドが回線上でハングすることに気づいています。rowsInserted = command.ExecuteNonQuery();タイムアウトを追加してトランザクションを追加しようとします。

+0

ここでProcessInsertsCollection()を呼び出しますか?新しいインサートが処理されるときに、後で再び呼び出されることはありません。 – pijemcolu

+0

私はそれをアプリケーションの開始時に呼びます。ある時間挿入するレコードではないかもしれませんが、processinsertscollectionが実行を停止した場合、タスク(_databaseTask)はコードをデバッグするときに実行中であることを示すべきではありません。私は正しい? – msk

+0

私があなただったら、try catch(実際にはプロダクション/デバッグ中にエラーを静かにしたくない)を取り除き、そのタスクのエントリーポイントとそのタスクの終了ポイントにブレークポイントを設定します。タスクがいつ開始するか、いつ終了するかを参照してください。 ProcessInsertCollectionが終了したら、タスクを再開する方法がありますか?タスクが実行中であると主張しています。実行している場合は、どちらの行ですか?あなたが見つけ出すスタートラインと出口ラインにbraekpointを置くことによって、 – pijemcolu

答えて

0

私はこの問題を発見しました。私は答えを加えます、多分それは誰かを助けるでしょう。

問題があります。rowsInserted = command.ExecuteNonQuery(); OracleCommandのデフォルトのタイムアウトは0であり、時間制限は適用されません。他のセッションでブロックされてしまったので、永遠にハングします。解決策は、OracleCommandのCommandTimeoutプロパティを使用して、コマンドのタイムアウトを追加することでした。そして、挿入を再試行するメカニズムを実装します。

関連する問題