2009-11-07 32 views
3

假情况:有一个班级(比方说BackgroundMagic),它有Start()Stop()方法。此类中的工作由单个线程完成,并且每X毫秒只是一个短循环。保持线程空闲或杀死它们/重新启动它们?

就管理停止/启动而言,哪个选项更好?无法决定走哪条路。

  1. 第一次调用Start()时,使用IsBackground = true初始化并启动线程。 使用一个简单的布尔标志来指示每个循环周围是否应该实际做任何工作,或者只是睡觉。初始化初始化后,让Stop()和Start()简单地控制布尔标志。由于IsBackground =应用程序退出时,该线程将被运行时停止并清除。
  2. 强行中止/加入/中断/停止上的任何内容,并在Start()上再次重新创建线程,而不是让线程四处闲逛。

...或者更好/更干净的方法来做到这一点?

回答

1

创建线程相当昂贵,因此标准的“工业强度”方法是使用标志来控制线程。对于同一想法的更大规模的变体,考虑线程池,例如Apache使用管理成千上万的线程,而没有很多明确的状态或痛苦的性能影响。

因此,在抽象中,我会为您的选项#1投票。但如果性能不是问题,并且选项#2的代码更容易推理,那就去做吧。

0

您还可以使用布尔标志来指示线程是否应该停止。它给你你的中断和停止代码。所以如果有工作和停止循环的话,那么两个bools。

您可以考虑的另一件事是使用Dispose模式并在处理对象时清理线程。

0

我会使用bool标志,但您需要确保它是正确锁定的或者只能从一个线程设置。你的循环应该是这样的

while (true) 
{ 
    if (shouldSleep) 
{ 
    Thread.Sleep(interval); 
    continue; 
} 

    doSomeWork(); 

if (shouldCancel) 
{ 
    CleanUpResources(); 
    break; 
} 
} 

这可以确保你能正确地发送线程睡觉,但也终止它。杀死一个线程从来不是一个好主意,因为线程没有机会清理使用的任何资源。你需要决定一个合适的睡眠时间间隔。它将确定你的线程需要启动的延迟。

第二个选项相当昂贵,线程创建涉及一些操作系统资源,启动时间也相当可观。如果线程娱乐不会经常发生,并且执行的工作量足够大,这将是合理的。您可以避免循环方法中涉及的复杂性。

1

互斥或信号量会比简单的布尔标志更好,因为它不需要重复检查标志的状态。简单地阻塞互斥体/信号量,当你想让线程运行时,释放互斥体/信号量,线程将运行一次。

1

线程池不适合长时间运行的任务。线程池非常适用于线程创建开销大大增加操作开销的短任务。 .NET 4框架中的TPL(Task Paralell Library)也是如此。

使用专门做这项工作的线程可能是一个好主意,但如何管理它可能是一件大事。如果您在检查工作之间简单地执行Thread.Sleep,那么效率就会降低,因为现在您无法正常旋转线程。这称为自旋锁(种类),并且只有在知道您正在等待的资源将很快释放锁时才有效。使用AutoResetEvent会更好。这样,线程只会被唤醒,因为生产者线程表示有工作要做。这样做的好处是不会浪费CPU资源来安排线程,如果没有任何事情做,并且它允许生产者和消费者之间更少的延迟。

要直接回答您的问题,是的,您可以使用某种bool正常关闭该线程(但我会将其标记为volatile)。这比中止线程好多了!

参见:

相关问题