2011-11-10 18 views
2

私は次のような構成があります:最初のオープンデータベース接続に使用パラレルforeachのタイムアウト優雅に近いすべてのワーカースレッド

  Parallel.ForEach(Program.config.Root.Elements("databases"), el => 
      { 
       try 
       {     
       DBConnection.OpenConnection(el.Attribute("database_alias").Value); 
       } 
       catch (Exception exc) 
       { 
        WriteLog(10, exc); 
       } 
      }); 

この構造を。しかし、第三者コンポーネントの反復のために、アプリケーション全体でハングすることがあります。そこで、私たちは補完を改善し、新しいものを手に入れます:

  Parallel.ForEach(Program.config.Root.Elements("databases"), el => 
      { 
       try 
       { 
        System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(DBConnection.OpenConnection)); 
        t.Start(el.Attribute("database_alias").Value); 

        // Handling 50 seconds timeout 
        if (!t.Join(50000)) 
        { 
         t.Abort(); 
         // Force closing because connection is hanging with "connecting" state 
         Program.myConnections[el.Attribute("database_alias").Value].Conn.Close();              
        }       
       } 
       catch (Exception exc) 
       { 
        WriteLog(10, exc); 
       } 
      }); 

しかし、今でも私たちは時間内に生きているスレッドを持っています。私は彼らがタスクマネージャーの金額を数えるのを見ることができます。誰もそれをどう管理するか知っていますか? ありがとうございます!

+0

を使用して 'Thread.Abort() '普通良い考えではない。他の方法で接続をキャンセルできませんか?また、Visual Studioデバッガのアクティブなスレッドは表示されないはずですか? – svick

+0

@svickそうは思わない。それはちょうど[Connection.Open()](http://www.devart.com/dotconnect/oracle/docs/Devart.Data.Oracle~Devart.Data.Oracle.OracleConnection.html)メソッドにぶら下がっています。 – kseen

+0

'ConnectionTimeout'の値は何ですか? 'Thread.Abort()'の代わりにそれを設定できませんか? – svick

答えて

0

Thread.Abortが機能していない場合、スレッドはおそらくネイティブコードでハングしている可能性があります。実際には、スレッドを中止するのは通常と非常に悪い考えです。とにかくです。 AppDomainをアンロードしている場合を除きます。

これは私が次に試すことです:一時的なAppDomainでスレッドを開始し、50秒のテスト後にアンロードします。

これが機能しない場合は、一時的なプロセスに移動する必要があります。

+0

これについていくつかサンプルを教えてください。 – kseen

+0

MSDNの例:[AppDomain](http://msdn.microsoft.com/en-us/library/system.appdomain.aspx)には、基本的な内容が記載されています。 –

+0

残念ながら、それはHRESULTエラーでダウンします。 – kseen

0

あなたのコードは、あなたがそれをリファクタリングすることができますので、もしご参照ください、理解することはやや困難である:

System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(DBConnection.OpenConnection)); 
t.Start(el.Attribute("database_alias").Value); 

// Handling 50 seconds timeout 
if (!t.Join(50000)) 
{ 
    t.Abort(); 
    // Force closing because connection is hanging with "connecting" state 
    Program.myConnections[el.Attribute("database_alias").Value].Conn.Close();              
} 

あなたの代わりにこれを行うことができるかどうか見てみてください。

Thread t = new Thread(()=> 
{ 
    try 
    { 
     // I'm not sure what the correct call is for OpenConnection, but the code below 
     // seems appropriate. If it's not right, then do it the right way 
     DBConnection.OpenConnection(el.Attribute("database_alias").Value); 
    } 
    catch(ThreadInterruptedException tie) 
    { 
     // Eat the exception or do something else (i.e. cleanup or whatever) 
    } 
}); 
t.IsBackground = true; 
t.Start(); 

// Handling 50 seconds timeout 
if (!t.Join(50000)) 
{ 
    // Interrupt the exception instead of aborting it (this should get you out of blocking states) 
    t.Interrupt(); 

    // Force closing because connection is hanging with "connecting" state 
    Program.myConnections[el.Attribute("database_alias").Value].Conn.Close();              
}