使用长时间的 Thread.Sleep 是个好主意吗?

Posted

技术标签:

【中文标题】使用长时间的 Thread.Sleep 是个好主意吗?【英文标题】:Is it a good idea to use longtime Thread.Sleep? 【发布时间】:2012-06-19 10:33:13 【问题描述】:

我有一份工作清单。每个作业都有自己的运行时间。他们需要在时机成熟时奔跑。我认为两种不同的方式。

public class Job 

    public int JobPeriod get;set; // for example as hour: daily = 24, weekly = 7 * 24, monthly = 30 * 24 
    public DateTime RunTime get;set

第一种方式:

我开始一个新的主线程。该线程以特定时间间隔(5 秒、10 秒等)检查作业。当作业的运行时间到来时,主线程将启动和完成作业。以这种方式持续运行的主线程。

while (true)

   lock (Locker)
   
       // checks job list.
       var jobs = foo.GetIncomingTimeJobs();
       foreach (var job in jobs)
       
           ParameterizedThreadStart ts = RunJob;
           var th = new Thread(ts);
           th.Start(job);
       

       Thread.Sleep(10000);
   


public void RunJob(Job job)

   // do somethings

第二种方式:

当应用程序启动时,我为作业列表中的每个作业创建一个新线程。所有这些创建的线程都将启动。当 Job 的线程启动时,Job 的线程会检查 Job 的运行时间。

例如:

var jobs = foo.GetAllJobs();
foreach (var job in jobs)

      ParameterizedThreadStart ts = RunJob;
      var th = new Thread(ts);
      th.Start(job);


public void RunJob(Job job)

    while (true)
    
       lock (Locker)
       
           // do somethings
           var period = job.JobPeriod * 60 * 1000;
           Thread.Sleep(period);
       
    

如果有十个作业,就会有十个线程。而这十根线永远不会结束。会睡觉,会继续,会睡觉,会继续......

线程休眠这么长时间正常吗?我应该使用哪种方式?或者还有其他方法可以做这样的事情吗?

【问题讨论】:

线程是昂贵的资源。为什么不使用计时器? @nikie 我想使用线程。没有其他原因。 @sinanakyazici - 如果你拒绝接受我们的建议,你为什么会在这里?你为什么要让你的主线程进入睡眠状态,我认为这样做没有任何好处。您的代码无效并且容易出现问题,我是根据经验说话的。至少你应该使用 Task 等 4.5 的特性。 @Ramhound 当我说“我想使用线程。没有其他原因”时,我并不是说我不在乎你的想法。这是因为我想知道有没有办法通过使用线程来解决这个问题。我不知道为什么我必须使用计时器。 @sinanakyazici:您的代码很可能会工作,但在大多数情况下调用 Thread.Sleep() 会浪费大量的处理时间和功率。不这样做的另一个原因是睡眠线程对外部事件完全没有响应。例如,如果您在 WinForms 应用程序的主 GUI 线程上执行睡眠 - 此应用程序将冻结指定时间并且不会响应任何用户操作。 【参考方案1】:

在大多数情况下,这两种方法都不正确。此类问题的通常解决方案是使用System.Threading.Timer。您的案例的示例代码如下所示:

private void CheckJobs(object state)

    lock (Locker)
    
        // checks job list.
        var jobs = foo.GetIncomingTimeJobs();
        foreach (var job in jobs)
        
            var thread = new Thread(foo);
            thread.Start();
        
    


private void StartProcessing()

    var timer = new System.Threading.Timer(CheckJobs, null, 0, 10000);

当您调用 StartProcessing() 函数时,将初始化计时器,并且每 10 秒检查一次作业列表。

如果您使用 Thread.Sleep(),您的应用程序将变得非常迟钝。

【讨论】:

以上是关于使用长时间的 Thread.Sleep 是个好主意吗?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring AOP 记录是个好主意吗?

使用私有继承隐藏实现是个好主意吗?

在 url 中使用冒号是个好主意?

将 Couchbase 与 Rails 一起使用是个好主意吗?

在 PHP mkdir 中使用模式 0664 是个好主意吗?

软删除是个好主意吗? [复制]