在 ManualResetEvent 或 Thread.Sleep() 之间进行选择
我不确定要采用哪种策略...我专注于完成操作,但我也希望将性能问题控制在最小范围...有一种名为 Execute()
通过使用 ManualResetEvent
void Execute()
{
taskHandle = new ManualResetEvent(false);
.
.
//delegate task to another thread
.
.
taskHandle.WaitOne();
}
或
通过使用简单的 while 构造
void Execute()
{
.
.
//delegate task to another thread
.
.
while (!JobCompleted)
Thread.Sleep(1000);
}
我应该采用这两种方法中的哪一种...为什么?
编辑:
Q2。如果我只有一个空的 while 结构怎么办?有什么区别...?
while(!JobCompleted);
编辑:(我之前收集的东西)
http://www.yoda.arachsys.com /csharp/threads/waithandles.shtml - 这篇文章说手动重置相对较慢,因为它们退出托管代码并返回...
I am not sure which strategy to adopt...I am focusing on my operation getting completed, but I'd also like to keep performance issues to a min too...there is a method called Execute() which has to wait (run synchronously) until an operation completes. This operation happens on another thread. There are 2 ways to implement the same thing...
By using ManualResetEvent
void Execute()
{
taskHandle = new ManualResetEvent(false);
.
.
//delegate task to another thread
.
.
taskHandle.WaitOne();
}
OR
By using a simple while construct
void Execute()
{
.
.
//delegate task to another thread
.
.
while (!JobCompleted)
Thread.Sleep(1000);
}
Which one of the two approaches should I adopt...why?
EDIT:
Q2. What if I just had an empty while contruct? Whats the difference...?
while(!JobCompleted);
EDIT: (something I gathered before)
http://www.yoda.arachsys.com/csharp/threads/waithandles.shtml - This article says manualresets are comparitively slower because they go out of managed code and back in...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
出于好奇,为什么是
ManualResetEvent
而不是AutoResetEvent
?无论哪种方式,都应采用操作系统原语,而不是睡眠-检查-睡眠方法。您还可以使用
Monitor
锁(通过Monitor.Enter
和Monitor.Exit
显式使用,或者通过lock
> 块),但该方法应该基于您实际正在做的事情;如果是“只有这些事物之一并且我需要独占访问”的场景,则使用Monitor
锁。如果是“出于资源访问以外的原因,我需要等待另一个线程完成”,则使用AutoResetEvent
或ManualResetEvent
。那么使用 Thread.Join 的建议是好的。
Thread
对象并且如果其中一个不成立(您无权访问,或者另一个线程不会终止,它只会发出“全部清除”信号),则 Thread.Join 不可行。
最糟糕的选择是
while(!JobCompleted);
因为这会使处理器对变量进行不必要的检查,而在它们之间没有任何暂停。是的,它会阻塞你的线程,直到操作完成,但你会最大化 CPU 使用率(或至少单个核心的价值)。
Out of curiosity, why
ManualResetEvent
and notAutoResetEvent
? Either way, go with the OS primitive over a sleep-check-sleep approach.You could also use a
Monitor
lock (either explicitly throughMonitor.Enter
andMonitor.Exit
, or through alock
block), but the approach should be based upon what you're actually doing; if it's a scenario of "there's only one of these things and I need exclusive access", then use aMonitor
lock. If it's "I need to wait until the other thread finishes for reasons other than resource access", then use anAutoResetEvent
orManualResetEvent
.The suggestions to use
Thread.Join
are good if (and only if)Thread
objectIf either isn't true (you don't have access, or the other thread won't terminate, it will just signal an "all clear") then
Thread.Join
isn't viable.The worst option is
while(!JobCompleted);
As that will tie up the processor with needless checks of the variable without any pause in between them. Yes, it will block your thread until the operation completes, but you'll max out CPU usage (or at least a single core's worth).
该事件可以更有效地利用处理器 - 您不必唤醒父线程来进行轮询。当事件触发时内核会唤醒你。
The event makes more efficient use of the processors- you're not having to wake the parent thread up to poll. The kernel will wake you up when the event fires.
如果您有权访问原始 Thread 对象,或者可以获得该访问权限,则最好使用
Thread.Join()
。编辑:此外,如果这是在 WinForms 或 WPF 等 GUI 中发生的,您可能需要考虑使用 后台工作人员
If you have access to the original Thread object, or can get that access, you're best off using
Thread.Join()
.Edit: Also, if this is taking place in a GUI like WinForms or WPF, you may want to consider using BackgroundWorker
使用 Thread.Sleep() 的主要缺点是您要决定线程将等待多长时间。您正在等待的操作可能会花费更多或更少的时间,并且一般来说,精确量化该时间是非常困难的。如果线程休眠时间太长,那么您就没有充分利用系统资源。
为了达到最佳效果,您应该使用
ManualResetEvent
(或AutoResetEvent
),以便在相关操作完成后立即恢复您的线程。The main disadvantage to using
Thread.Sleep()
is that you are making the decision on how long the thread will wait. The operation you are waiting for may take more or less time, and in general, it is very difficult to precisely quantify that time. If the thread sleeps too long, then you are not making best use of system resources.In order to be optimal, you should use
ManualResetEvent
(orAutoResetEvent
) so that your thread is resumed as soon as the dependent operation finishes.ManualResetEvent 绝对是最佳选择。
从您提供的代码片段来看,您似乎正在委托 Execute 方法中的执行。如果是这种情况,并且您只委派一个任务,那么如果您必须等待响应,为什么还要委派给另一个线程呢?您也可以同步执行该过程。
ManualResetEvent is definitely the way to go.
From the code snippet you supplied, it looks like you are delegating the execution within your Execute method. If this is the case, and you are only delegating a single task, why are you delegating to another thread at all if you have to wait for the response? You may as well just execute the process synchronously.
它们可能比 等待/脉冲组合,我认为您应该在这里使用。但
Manual/AutoResetEvents
将比您执行的任何Thread.Sleep(x)
快得多,即使您选择x = 1
也是如此。即使您将 Windows 计时器分辨率降低到 1 毫秒。然后,一个核心将以 100% 的速度旋转,直到条件成立,从而从其他线程中窃取时间,而这些线程可能会使用它来做一些有用的事情,例如计算“愤怒的小鸟”的帧 - 或者 CPU 可以简单地冷却一下,延迟全球变暖的可怕影响还会持续几纳秒。
They are probably slower than say a Wait/Pulse combo, which you should use here in my opinion. But
Manual/AutoResetEvents
will be way faster than anyThread.Sleep(x)
that you do, even if you choosex = 1
. And even if you lower the Windows timer resolution to 1ms.Then one core will spin at 100% until the condition turns true, stealing away time from other threads that might instead use it to do something useful, like calculating frames for "Angry Birds" - or the cpu could simply cool off a bit, delaying the dire effects of global warming for some further nanoseconds.
两种方法基本上都做同样的事情。然而,while 循环更明确一点,因为您可以指定睡眠时间。尽管我会使用 XXXResetEvent 类,这些类应该在您工作的场景中使用。我假设线程类现在或稍后会使用更强大的线程代码来实现,以处理多核处理器上的线程关联。
Both approaches do the same thing basically. The while loop is little bit more explicit however, since you can specify the sleep time. Although I would use the XXXResetEvent classes which are meant to be used in the scenario your working in. I would assume the threading classes would be implemented now or later with more robust threading code to handle maybe thread affinity on multi core processors.