伪情况:有一个类(比方说BackgroundMagic
),它有Start()
和Stop()
方法。这个类中的工作由一个单独的线程完成,并且每X毫秒只是一个短循环。
就管理停止/启动而言,哪些选项更好?无法决定走哪条路。
IsBackground
= true初始化并启动线程。 使用一个简单的bool标志来指示每个循环是否应该实际执行任何工作,或只是睡眠。初始初始化后,让Stop()和Start()简单地控制bool标志。当应用程序退出时,IsBackground
= true,线程将被运行时停止并清理。......或者更好/更清洁的方式吗?
答案 0 :(得分:9)
既不!使用Thread Pool!
答案 1 :(得分:2)
线程创建相当昂贵,因此标准的“工业强度”方法是使用标志来控制线程。对于同一想法的更大规模的变体,请考虑例如线程池。 Apache使用它来管理数千个线程,而没有大量明确的状态或痛苦的性能损失。
所以在摘要中,我会投票给你的选项#1。但是,如果性能不是一个问题而选项#2代码更容易推理,那就去吧。
答案 2 :(得分:2)
互斥锁或信号量比简单的布尔标志更好,因为它不需要重复检查标志的状态。只需阻塞互斥锁/信号量,当您希望线程运行时,释放互斥锁/信号量,线程将运行一次。
答案 3 :(得分:2)
线程池不适合长时间运行的任务。线程池非常适合于短期任务,其中线程创建的开销会使操作的开销大幅增加。 .NET 4框架中的TPL(任务并行库)也是如此。
使用专门用于完成这项工作的线程可能是一个好主意,但是如何管理它可能是一件大事。如果你只是在检查工作之间做Thread.Sleep
那么那就不那么有效了,因为现在你没有充分的理由让线程旋转。这称为自旋锁(类型),只有当您知道您正在等待的资源将很快释放锁时才有效。使用AutoResetEvent
会更好。这样线程只会唤醒,因为生产者线程表示有工作要做。这样做的好处是,如果没有任何事情可以浪费CPU资源来安排线程,并且它可以减少生产者和消费者之间的延迟。
要直接回答您的问题,是的,您可以使用某种bool
来优雅地关闭该帖子(我会将其标记为volatile
)。这比中止线程要好得多!
请参阅:
答案 4 :(得分:1)
您还可以使用bool标志来指示线程是否应该停止。它为您提供中断和停止代码。因此,如果有工作,则有两个用于停止循环。
您可以考虑的另一件事是使用Dispose模式并在处理对象时清理线程。
答案 5 :(得分:1)
我会使用bool标志,但你需要确保它被正确锁定或仅从一个线程设置。你的循环应该是这样的
while (true)
{
if (shouldSleep)
{
Thread.Sleep(interval);
continue;
}
doSomeWork();
if (shouldCancel)
{
CleanUpResources();
break;
}
}
这可确保您可以将线程发送到睡眠状态,但也可以正确终止它。如果你可以避免它,那么杀死一个线程永远不是一个好主意,因为线程没有机会清理所使用的任何资源。您需要确定适当的睡眠间隔。它将确定您的线程启动所需的延迟。
第二个选项相当昂贵,线程创建涉及一些OS资源,启动时间也相当可观。如果线程重新创建不会经常发生并且执行的工作量足够大,那么这将是合理的。您可以避免循环方法中涉及的复杂性。