1

I wrote some code that mass imports a high volume of users into AD. To refrain from overloading the server, I put a thread.sleep() in the code, executed at every iteration.

Is this a good use of the method, or is there a better alternative (.NET 4.0 applies here)?

Does Thread.Sleep() even aid in performance? What is the cost and performance impact of sleeping a thread?

4

7 回答 7

2

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

我的意见是使用 Thread.Sleep() 方法并遵循我之前的建议。在您的具体情况下,我想您不会有任何问题。如果你努力寻找关于 SO 的相同主题,我相信你会找到关于我之前总结的更好的解释。

如果您无法从被调用服务接收反馈,就像在典型的事件驱动系统上发生的那样(抽象地说......我们也可以说回调或任何信息以了解服务如何受您的调用影响),睡眠可能是要走的路。

于 2012-07-30T23:46:16.740 回答
1

如果您想要的不是使服务器超载,则可以降低线程的优先级。

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

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

就我个人而言,我从来没有发现必须使用 Thread.Sleep 的情况。现在我正在开发一个 ASP.NET MVC 应用程序,它使用后台线程将大量数据从数据库加载到内存缓存中,然后将一些数据写入数据库。我用来防止这个线程吃掉我所有的网络服务器和数据库处理器的唯一功能是将线程优先级降低到最低级别。如果使用普通优先级线程,该线程将需要大约 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 -设计程序.aspx

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

于 2012-07-30T23:51:12.107 回答
1

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

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

在使用 AD 时,我看到域控制器在过多的命令进入(类似于 DOS 攻击)并导致服务器爬行或崩溃时崩溃。我认为通过使用 sleep 方法,您正在创建一个可管理和可测量的流程。

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

希望这可以帮助; 干杯!

于 2012-07-31T00:05:12.533 回答
0

Thread.Sleep() 是一种无 CPU 的等待状态。它的开销应该很小。如果 execute 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
}

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

于 2012-07-31T00:06:09.447 回答
0

您可以改为BelowNormal 优先安排线程。也就是说,如果其他东西使服务器过载,这可能会导致您的任务永远不会运行。(假设 Windows 调度按照调度线程文档中提到的“某些操作系统”的方式工作。)

也就是说,您说您正在将数据移动到 AD 中。如果超出了网络,那么与 AD 端的 I/O 和处理相比,您的代码对 CPU 的影响完全可以忽略不计。

于 2012-07-30T23:53:18.280 回答
0

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

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

于 2012-07-30T23:54:50.523 回答
0

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

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

于 2012-07-30T23:55:36.840 回答