【问题标题】:What causes the thread to hang and doesn't throw anything even after 20 hours是什么导致线程挂起并且即使在 20 小时后也不会抛出任何东西
【发布时间】:2012-06-01 02:54:57
【问题描述】:

我在线程中有线程,最后一个子线程只是挂起,现在 20 小时内没有抛出任何东西。我的代码是这样的:

bool end = false;

var t1 = new Thread(() =>
{
    // ...

    var t2 = new Thread(() =>
    {
        try
        {
            foreach(Data data in datas2)
            {
                foreach(SubData subdata in data.SubDatas)
                {
                    var t3 = new Thread(() =>
                    {
                        this.SaveData(subdata.RetrieveData());
                    }); t3.Start();

                    if (!t3.Join(1800000))
                    {
                        t3.Abort();
                        throw new TimeoutException("The execution of method is taking too long.");
                    }
                }
            }
        } catch { throw; }
        finally { end = true; }
    }); t2.Start();
}); t1.Start();

它永远不会通过t2finally 块,也不会抛出任何错误。这里发生了什么?

我的代码使用 C#,框架 4,在 Visual Studio 2010 Pro 中构建。

请帮忙。提前致谢。


编辑:
感谢大家的帮助。我找到了答案,它是

无限循环。

因为这个愚蠢的错误,我们的生产停了一周。啊。似乎我们的系统上有一个验证,它只为某些数据创建一个无限循环。感谢大家热心解答这个问题。

【问题讨论】:

  • t3 是否完成执行?你什么时候使用end 变量?
  • 取决于 SaveData 和 RetrieveData 中发生的情况
  • @YoryeNathan t3 没有完成执行。我有另一个线程检查t2 是否已结束。 end 实际上是一个类型为private volatile bool 的类变量。
  • 圆括号不平衡。您的示例中没有显示哪部分代码?
  • 看起来很适合 Tasks Parallel Library (msdn.microsoft.com/en-us/library/dd460717.aspx)。

标签: c# multithreading .net-4.0


【解决方案1】:

我不知道这是否是你的问题....

但是,Thread.Abort 会引发一个异常(一个特殊的异常,即使您捕获它,一旦捕获并最终完成它会自动重新抛出自身,除非您清除 abort )。如果 SaveData 和 RetriveData 中的代码捕获到异常,然后在捕获中或最终被阻塞,它不会中止。

【讨论】:

  • 你说的要么被抓住,要么最终被阻止是什么意思?它是什么以及如何被阻止?
  • 如果它在等待什么?锁在别的东西上?在另一个线程上调用某些东西,或者类似的东西。
【解决方案2】:

可能在 SaveData 或 RetrieveData 中发生了一些我们不知道的事情。您可能正在执行我们不知道的极长/重复性 I/O。

此外,我不认为这段代码正在做你认为它正在做的事情。见我的//注意:下面:

            foreach(SubData subdata in data1.SubDatas)
            {
                var t3 = new Thread(() =>
                {
                    this.SaveData(subdata.RetrieveData());
                }); t3.Start();

                // NOTE: Here you are blocking each iteration of T2 
                // while T3 runs.  There is no reason to be running 
                // another thread here- just call SaveData/RetrieveData 
                // from T2.  Additionally, because this is executing in 
                // a double-nested loop, you might be doing this many, 
                // many times.  I'd suggest looking into ThreadPool or TPL.

                if (!t3.Join(1800000))
                {
                    t3.Abort();
                    throw new TimeoutException("The execution of method is taking too long.");
                }
            }

【讨论】:

  • 我实际上打算在t3 运行时阻止t2,我只是将它放到另一个线程中,以便在运行时间过长时将TimeoutException 添加到其中。 RetrieveData 是一个连接到 WCF 服务的内存密集型进程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多