我不确定采用哪种策略......我专注于我的操作完成,但我也想将性能问题保持在最低限度......有一种方法叫做执行( )必须等待(同步运行)直到操作完成。此操作发生在另一个线程上。有两种方法可以实现同样的目的......
使用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(!JobCompleted);
编辑:(之前我收集过的东西)
http://www.yoda.arachsys.com/csharp/threads/waithandles.shtml - 这篇文章说手动重置比较慢,因为它们离开了托管代码并重新进入......
答案 0 :(得分:13)
出于好奇,为什么ManualResetEvent
而不是AutoResetEvent
?无论哪种方式,通过睡眠 - 检查 - 睡眠方法来使用OS原语。
你也可以使用Monitor
锁定(通过Monitor.Enter
和Monitor.Exit
明确地或通过lock
块),但方法应该基于你的实际上是在做如果它是“只有一个事物并且我需要独占访问”的场景,那么使用Monitor
锁定。如果是“我需要等到其他线程完成,而不是资源访问”,请使用AutoResetEvent
或ManualResetEvent
。
如果(且仅限于)
,使用Thread.Join
的建议是好的
Thread
对象如果其中任何一个不是真的(你没有访问权限,或者其他线程不会终止,它只会发出“全部清除”信号),那么Thread.Join
就不可行了。
最糟糕的选择是
while(!JobCompleted);
因为这会将处理器与变量的不必要检查联系起来而不会在它们之间产生任何停顿。是的,它将阻止你的线程,直到操作完成,但你将最大化CPU使用率(或至少一个核心的价值)。
答案 1 :(得分:4)
该事件可以更有效地使用处理器 - 您不必将父线程唤醒以进行轮询。当事件发生时,内核会将你叫醒。
答案 2 :(得分:2)
如果您有权访问原始的Thread对象,或者可以获得该访问权限,那么最好使用Thread.Join()
。
编辑:此外,如果这是在WinForms或WPF等GUI中进行的,您可能需要考虑使用BackgroundWorker
答案 3 :(得分:2)
使用Thread.Sleep()
的主要缺点是您正在决定线程将等待多长时间。您正在等待的操作可能需要更多或更少时间,并且通常,很难精确地量化该时间。如果线程睡眠时间过长,那么您没有充分利用系统资源。
为了达到最佳效果,您应该使用ManualResetEvent
(或AutoResetEvent
),以便在从属操作完成后立即恢复您的线程。
答案 4 :(得分:1)
ManualResetEvent绝对是最佳选择。
从您提供的代码段中,您似乎在Execute方法中委派执行。如果是这种情况,并且您只委派一个任务,那么如果您必须等待响应,为什么还要委托给另一个线程呢?您也可以同步执行该过程。
答案 5 :(得分:1)
手动重置比较慢,因为它们离开托管代码并重新进入..
他们可能比说 Wait/Pulse combo要慢,我认为你应该在这里使用。但即使您选择Manual/AutoResetEvents
,Thread.Sleep(x)
也会比您所做的x = 1
更快。即使您将Windows计时器分辨率降低到1毫秒。
如果我在构造时只是空了怎么办?差异是什么......?
然后一个核心将以100%旋转直到条件变为真,从其他线程中偷走时间,而不是使用它来做一些有用的事情,比如计算“愤怒的小鸟”的帧 - 或者cpu可以简单地冷却一个比特,将全球变暖的可怕影响推迟了一些纳秒。
答案 6 :(得分:0)
两种方法基本上都做同样的事情。然而,while循环更明确,因为您可以指定睡眠时间。虽然我会使用XXXResetEvent类,这些类将用于您正在使用的场景中。我假设现在或稍后实现线程类,使用更强大的线程代码来处理多核处理器上的线程关联。