Параллельный тайм-аут Foreach изящно закрывает каждый рабочий поток - PullRequest
2 голосов
/ 10 ноября 2011

У меня есть следующая конструкция:

            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);
                }
            });

Но даже сейчас у нас есть живые темы во времени. Я вижу их подсчет суммы в диспетчере задач. Кто-нибудь знает, как с этим справиться? Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 11 ноября 2011

Ваш код несколько сложен для понимания, поэтому, пожалуйста, посмотрите, можете ли вы его реорганизовать:

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();                                                     
}
0 голосов
/ 10 ноября 2011

Если Thread.Abort не работает, то потоки, вероятно, зависают в собственном коде.На самом деле, прерывание потока - это обычно очень плохая идея в любом случае.Если вы не выгружаете домен приложений.

Вот что я бы попробовал сделать следующее: запустить потоки во временном домене приложений и выгрузить его после 50-секундного теста.

Если это не сработаетвам придется переместить их во временный процесс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...