Thread.Sleep()用于防止服务器过载

时间:2012-07-30 23:42:42

标签: c# multithreading

我写了一些代码,大量将大量用户导入AD。为了避免服务器过载,我在代码中放了一个thread.sleep(),每次迭代都会执行。

这是一个很好用的方法,还是有更好的选择(这里适用.NET 4.0)?

Thread.Sleep()是否有助于提高性能?睡眠线程的成本和性能影响是什么?

7 个答案:

答案 0 :(得分:2)

Thread.Sleep()方法只会将线程置于暂停状态达指定的时间。我可以告诉你有三种不同的方法来实现从三种不同类型调用方法的相同Sleep()。它们都有不同的功能。无论如何,最重要的是,如果在主UI线程上使用Sleep(),它将在该暂停期间停止处理消息,并且GUI将看起来被锁定。您需要使用BackgroundWorker来运行您需要睡觉的工作。

我的意见是使用Thread.Sleep()方法,并按照我以前的建议。在你的具体情况下,我猜你没有问题。如果你付出一些努力在SO上寻找相同的主题,我相信你会找到更好的解释我之前总结的内容。

如果您无法从被叫服务收到反馈,就像在典型的事件驱动系统上发生的那样(以抽象方式进行交谈。我们也可以说回调或任何信息,以了解服务如何受到您的影响打电话),睡眠可能是你要走的路。

答案 1 :(得分:1)

如果你想要的不是服务器的重载,你可以降低线程的优先级。

Thread.Sleep()不消耗任何资源。但是,正确的方法是将线程的优先级设置为低于Normal的值:Thread.Current.Priority = ThreadPriority.Lowest例如。{/ p>

Thread.Sleep不是“邪恶,不要永远”,但也许(只是可能)你需要使用它反映了解决方案设计的一些缺点。但这根本不是一个规则。

就个人而言,我从未发现我 使用Thread.Sleep的情况。 现在我正在开发一个ASP.NET MVC应用程序,它使用后台线程将大量数据从数据库加载到内存缓存中,之后将一些数据写入数据库。 我用来防止这个线程占用我所有的webserver和db处理器的唯一功能是将线程优先级降低到最低级别。如果使用普通优先级线程,该线程将花费大约35分钟来结束所有操作,而不是7分钟。在进程结束时,线程将对数据库服务器进行大约230k的选择,但这并没有以一种敏感的方式影响我的数据库或Web服务器性能。

提示:如果您使用ThreadPool中的线程,请记住将优先级设置回Normal。

在这里你可以阅读Thread.Priority: http://msdn.microsoft.com/en-us/library/system.threading.thread.priority.aspx

这是一篇关于为什么不在生产环境中使用Thread.Sleep的好文章: http://msmvps.com/blogs/peterritchie/archive/2007/04/26/thread-sleep-is-a-sign-of-a-poorly-designed-program.aspx

EDIT 像其他人所说的那样,也许只是减少你的线程优先级不会阻止线程向AD发送大量命令/数据。如果你重新考虑所有的事情并使用计时器或类似的东西,也许你会得到更好的结果。我个人认为降低优先级可以解决您的问题,尽管我认为您需要使用您的数据进行一些测试,以查看您的服务器和该流程中涉及的其他服务器会发生什么。

答案 2 :(得分:1)

我认为Thread.Sleep是处理这个问题的一种方法; @cHao是正确的,使用计时器将允许您以另一种方式执行此操作。实质上,您正在尝试减少在一段时间内发送到AD服务器的命令数量。

在使用计时器时,您需要设计一种检测故障的方法(比try / catch更直观)。例如,如果您的服务器开始停止并且响应速度较慢,那么您将继续堆叠服务器无法处理的命令(可能会在其他错误中级联)。

使用AD时,我看到域控制器在有太多命令进入(类似于DOS攻击)并且使服务器爬行或崩溃时吓坏了。我认为通过使用睡眠方法,您可以创建一个可管理且可测量的流程。

在这种情况下,使用具有低优先级的线程可能将其降低速度,但不会降低到任何可控级别。线程优先级只是发送命令的机器的一个因素,而不是服务器必须处理它们的因素。

希望这会有所帮助;干杯!

答案 3 :(得分:0)

您可以在BelowNormal priority安排线索。也就是说,如果其他东西超载了服务器,这可能会导致您的任务永远不会运行。 (假设Windows调度的工作方式与documentation on scheduling threads提及的某些操作系统的结合方式相同。)

那就是说,你说你正在将数据转移到AD中。如果它超过了nework,那么与I / O和AD端处理相比,代码的CPU影响完全可以忽略不计。

答案 4 :(得分:0)

我没有看到任何问题,除了在你让线程进入睡眠状态期间,该线程将不会响应。如果这是您的主要线程,那么您的GUI将变得无响应。如果它是后台线程,那么您将无法与之通信(例如取消它)。如果你睡觉的时间很短,那就不重要了。

我不认为降低线程的优先级会有所帮助1)您的代码甚至可能不在服务器上运行2)服务器完成的大部分工作可能不会出现在您的线程上反正。

答案 5 :(得分:0)

Thread.sleep不会有助于提高性能(除非你的线程必须等待某些资源)。它至少会产生一些开销,并且无法保证您睡眠的时间。操作系统可以决定让您的线程休眠时间超过您指定的时间。

因此,在调用Thread.Sleep()之间进行大量工作更有意义。

答案 6 :(得分:0)

Thread.Sleep()是一个没有CPU的等待状态。它的开销应该很小。如果执行Thread.Sleep(0),你不一定要睡觉,但是你自愿放弃你的时间片,这样调度程序可以让优先级较低的线程运行。

您还可以通过设置Thread.Priority来降低线程的优先级。

限制任务的另一种方法是使用Timer

// instantiate a timer that 'ticks' 10 times per second (your ideal rate might be different)
Timer timer = new Timer( ImportUserIntoActiveDirectory , null , 0 , 100 ) ;

其中ImportUserIntoActiveDirectory是一个只将用户导入AD的事件处理程序:

private void ImportUserIntoActiveDirectory( object state )
{
  // import just one user into AD
  return
}

这使您可以拨入内容。在线程池工作线程上调用事件处理程序,因此您不会占用主线程。让操作系统为您完成工作:您所做的只是决定您的目标交易率。