ManualResetEvent vs while循环

时间:2013-12-09 06:50:23

标签: c# manualresetevent

ManualResetEvent基本上对其他线程说“你只能在收到信号时继续”,并用于暂停某些线程的执行,直到满足某些条件。我想问的是,为什么我们可以通过使用while循环轻松实现我们想要的功能时手动复制?请考虑以下背景:

public class BackgroundService {

ManualResetEvent mre;
public BackgroundService() {
    mre = new ManualResetEvent(false);
}
public void Initialize() {
    // Initialization
    mre.Set();
}

public void Start() {
    mre.WaitOne();
    // The rest of execution
}
}

有点类似于

public class BackgroundService {

bool hasInitialized;
public BackgroundService() {

}
public void Initialize() {
    // Initialization
    hasInitialized = true;
}

public void Start() {
    while (!hasInitialized)
    Thread.Sleep(100);
    // The rest of execution
}
}

是否有任何特定的上下文,其中ManualResetEvent比while循环更合适?

2 个答案:

答案 0 :(得分:3)

  

是否有任何特定的上下文,其中ManualResetEvent比while循环更合适?

绝对。有两个主要原因:延迟和效率。

上下文切换线程以使其再次运行是相对昂贵的,当它刚刚恢复睡眠时,你给出的方法平均需要50ms才能响应hasInitialized变量正在设定 - 假设它完全响应。 (你没有任何明确的内存障碍,因此线程可能根本不会看到对变量的更改。我怀疑调用Thread.Sleep会有效地增加内存障碍,但不能保证。 )使用OS / CLR级同步原语,线程可以更快地响应。

答案 1 :(得分:0)

使用提供ManualResetEvent之类的信号更有效。使用while循环意味着大约每100毫秒,即每秒10次,其他线程必须停止运行,因此您的线程必须运行检查条件,当条件大多为假时,此上下文切换效率低下。

然而,在你的代码中出现了一些非常可疑的东西,为什么在初始化某些东西时你会进行这样的代码轮询?如果初始化是异步的,则已经存在一些通知机制,例如,回调,完成后不需要轮询。