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循环更合适?
答案 0 :(得分:3)
是否有任何特定的上下文,其中ManualResetEvent比while循环更合适?
绝对。有两个主要原因:延迟和效率。
上下文切换线程以使其再次运行是相对昂贵的,当它刚刚恢复睡眠时,你给出的方法平均需要50ms才能响应hasInitialized
变量正在设定 - 假设它完全响应。 (你没有任何明确的内存障碍,因此线程可能根本不会看到对变量的更改。我怀疑调用Thread.Sleep
会有效地增加内存障碍,但不能保证。 )使用OS / CLR级同步原语,线程可以更快地响应。
答案 1 :(得分:0)
使用提供ManualResetEvent
之类的信号更有效。使用while
循环意味着大约每100毫秒,即每秒10次,其他线程必须停止运行,因此您的线程必须运行检查条件,当条件大多为假时,此上下文切换效率低下。
然而,在你的代码中出现了一些非常可疑的东西,为什么在初始化某些东西时你会进行这样的代码轮询?如果初始化是异步的,则已经存在一些通知机制,例如,回调,完成后不需要轮询。