0

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

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 循环更合适?

4

2 回答 2

3

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

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

上下文切换线程以使其再次运行相对昂贵,当它只是要重新进入睡眠状态时,您给出的方法将平均需要 50 毫秒来响应hasInitialized正在设置的变量 - 假设它完全响应. (您没有任何显式的内存屏障,因此线程可能根本看不到变量的更改。我怀疑调用Thread.Sleep有效地添加了内存屏障,但不能保证。)使用 OS/CLR级同步原语,线程可以更快地响应。

于 2013-12-09T06:53:50.697 回答
0

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

但是,在您的代码中有些东西闻起来很可疑,为什么在初始化某些东西时会有这样的代码轮询?如果初始化是异步的,那么已经有一些通知机制,例如回调,当它完成时,轮询是不必要的。

于 2013-12-09T06:58:38.847 回答