当父线程休眠时,子线程是否也会休眠?

7

当父线程休眠时,子线程也会休眠吗?

现在主线程是UI界面。我使用任务工厂(称为线程2)在主线程中创建了20个子线程。在这20个子线程中,我再次使用子工厂(称为线程3)创建了另外10个子线程。

现在,在线程2中有一个无限循环。在无限循环中检查线程3是否已完成。如果已完成,则释放已完成的线程并启动另一个线程。我在无限while循环中每250毫秒使用一次sleep进行检查。因此,当线程2处于休眠状态时,线程3是否也会休眠,还是它们是独立的?下面是代码:

while (true)
{
    int irActiveThreadCount = 0;
    int irFinishedLast = -1;

    for (int i = 0; i < irPerMainSiteThreadCount; i++)
    {
        if (MainSitesTaskList[irWhichMainTask, i] == null)
        {
            irFinishedLast = i;
            break;
        }
        if (MainSitesTaskList[irWhichMainTask, i].IsCompleted == true)
        {
            irFinishedLast = i;
            break;
        }
    }

    for (int i = 0; i < irPerMainSiteThreadCount; i++)
    {
        if (MainSitesTaskList[irWhichMainTask, i] != null)
            if (MainSitesTaskList[irWhichMainTask, i].IsCompleted == false)
            {
                irActiveThreadCount++;
            }
    }

    if (irFinishedLast > -1)
    {
        var newTask = Task.Factory.StartNew(() =>
        {
            fcStartSubPageCrawl(srMainSiteURL, srMainSiteId, irWhichMainTask);
        });
        lock (lockerMainSitesArray)
        {
            if (MainSitesTaskList[irWhichMainTask, irFinishedLast] != null)
                MainSitesTaskList[irWhichMainTask, irFinishedLast].Dispose();
            MainSitesTaskList[irWhichMainTask, irFinishedLast] = newTask;
        }
    }

    Thread.Sleep(250);

    srQuery = "myquery";
    using (DataSet dsTemp = DbConnection.db_Select_Query(srQuery))
    {
        if (dsTemp != null)
            if (dsTemp.Tables.Count > 0)
                if (dsTemp.Tables[0].Rows.Count == 0)
                {
                    break;
                }
    }
}

5
首先,这听起来像是一种非常重的线程架构;你确定需要所有这些线程吗?每当你浪费整个线程,只是让它大部分时间处于休眠状态,这是一个非常糟糕的迹象;就像你不会分配一个百万字节的数组,然后从未放任何东西进去一样,当你创建一个空闲线程时也是如此。其次,我不明白为什么你在这里问这个问题。 你已经编写了代码;只需运行它并查看它的操作即可。如果“子”线程没有进入睡眠状态,你就会知道答案。 - Eric Lippert
Eric Lippert,我也在询问保持一定数量的线程始终处于活动状态的方法。 - Furkan Gözükara
听起来对于一个爬虫来说太复杂了。创建一个任务列表并将其投入线程池。 - David Heffernan
1
David的观点是有很多方法可以使一个线程等待另一个线程。使用它们!这比疯狂地睡一会儿、醒来、再睡觉、醒来......要好得多。相反,创建一个信号线程的对象,让一个线程等待信号,另一个线程激活信号。让操作系统处理线程管理;你不必做所有那些事情。每当你看到有人在线程上调用Sleep,都应该挥舞大红旗,说“这个人没有有效地管理他的线程”。有更好的方法。 - Eric Lippert
2
为了保持一些线程以备后用,不要自己动手。使用线程池。这就是它的作用。根据你的问题,听起来你(1)没有很多处理线程的经验,(2)正在尝试重新发明已经存在并由专家精心调整的大量技术。我看你正在使用任务并行库来表示你的问题,所以让去担心如何创建最有效地解决问题的线程数。 - Eric Lippert
显示剩余4条评论
5个回答

11

实际上不存在所谓的“父”线程。一个线程可以启动另一个线程,但它们之间没有特定的关系。例如,启动线程可以终止而不会导致任何新线程死亡。

启动线程的睡眠绝对不会影响其他线程。


1
@MonsterMMORPG:线程池的整个意义在于它确实保持一定数量的线程处于活动状态,等待更多的工作。 - Jon Skeet
启动一百万个线程比像Monster那样让它们等待更耗时,不是吗? - Skuta
@Skuta:谁说要用一百万个线程了?我说过我会使用线程池。 - Jon Skeet
@JonSkeet,前台线程和后台线程之间不是有所区别吗?我有时会看到人们错误地使用子/父术语来指代这种差异。https://learn.microsoft.com/en-us/dotnet/standard/threading/foreground-and-background-threads - chtenb
@ChieltenBrinke:前景/背景只与线程是否保持进程活动有关。这完全独立于任何“父/子”概念。 - Jon Skeet
显示剩余8条评论

1

没有父线程和子线程的概念。这意味着,子线程不会在父线程休眠时休眠。


谢谢回答。我只是想知道这个方法是否适合保持一定数量的线程活动? - Furkan Gözükara
为什么你想要“保持一定数量的线程处于活动状态”?通常情况下,线程会在完成任务后自然结束它们的生命周期。 - John Saunders
这是一个爬虫程序。因此,我希望能够设置爬虫代理数量。 - Furkan Gözükara

1
Thread.Sleep(...)

只会暂停当前线程。

请查看这里:Thread.Sleep 方法

因此,所有其他线程将继续工作。


0

每个线程都是完全独立的。线程之间唯一可能的连接是当所有非后台线程完成时,程序结束,因此后台线程也会停止。如果一个线程休眠,其他线程将继续工作(并且可能更快,因为有一个线程少在工作)。如果需要同步线程,有各种类可以实现(通常使用锁(不是一个类)、互斥量、信号量等)。


0

其他人说得没错,在 .Net 中没有“父线程”的概念。等待一个线程不会导致其他线程等待(除非涉及到一些同步,比如使用 lock)。

但还有另一点:你的代码并没有创建新的线程,至少不一定是这样。当你调用 Task.Factory.StartNew() 时,任务通常会在线程池线程上调度。如果没有可用的线程,并且线程数尚未达到允许的最大数量,那么就会创建新的线程。但在其他情况下,它不会创建新线程。任务要么将重用现有的空闲线程,要么将等待,直到有一个线程可用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接