Parallel Foreach Timeout优雅地关闭每个工作线程

时间:2011-11-10 17:30:04

标签: c# .net database multithreading thread-safety

我有以下结构:

            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 :(得分:0)

如果Thread.Abort不起作用,则线程可能会挂起本机代码。实际上,无论如何,中止一个线程通常都是非常糟糕的主意。除非您正在卸载AppDomain。

这就是我接下来要尝试的内容:在临时AppDomain中启动线程并在50秒测试后卸载它。

如果这不起作用,您必须将它们移至临时过程。

答案 1 :(得分: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();                                                     
}