简体   繁体   English

ManualResetEvent与while循环

[英]ManualResetEvent vs while loop

ManualResetEvent basically says to other threads "you can only proceed when you receive a signal to continue" and is used to pause execution for certain threads until certain condition has been fulfilled. ManualResetEvent基本上对其他线程说“您只能在收到继续信号时才能继续”,并且用于暂停某些线程的执行,直到满足某些条件为止。 What I want to ask is that why ManualResetEvent when we could easily achieve what we want by using a while loop? 我想问的是为什么为什么在使用while循环可以轻松实现我们想要的目标时使用ManualResetEvent? Consider the following context: 考虑以下情况:

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
}
}

is somewhat similar to 有点类似于

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
}
}

Is there any particular context where ManualResetEvent is more suitable than a while loop? 在任何特定的上下文中,ManualResetEvent比while循环更合适吗?

Is there any particular context where ManualResetEvent is more suitable than a while loop? 在任何特定的上下文中,ManualResetEvent比while循环更合适吗?

Absolutely. 绝对。 There are two primary reasons: latency and efficiency. 主要有两个原因:延迟和效率。

Context-switching the thread to start it running again is relatively expensive, when it's just going to go back to sleep, and the approach you've given will take an average of 50ms to respond to the hasInitialized variable being set - assuming it responds at all. 上下文切换线程以使其再次运行是相对昂贵的,当它刚要回到睡眠状态时,您所提供的方法将平均花费50毫秒来响应所设置的hasInitialized变量-假设它在所有。 (You don't have any explicit memory barriers, so it's possible that the thread won't actually see a change to the variable at all. I suspect that calling Thread.Sleep effectively adds a memory barrier, but it's not guaranteed.) With OS/CLR-level synchronization primitives, a thread can respond much faster. (您没有任何显式的内存屏障,因此线程实际上可能根本看不到变量的变化。我怀疑调用Thread.Sleep有效地增加了内存屏障,但不能保证。)在OS / CLR级同步原语中,线程可以更快地响应。

Using signals such as that provided ManualResetEvent is more efficient. 使用诸如ManualResetEvent所提供的信号更为有效。 Using a while loop as you have means after roughly every 100 milliseconds, ie 10 times a second, other threads have to stop running so your thread to check the condition has to run, this context switch when the condition is mostly false is less efficient. 使用while循环意味着大约每100毫秒(即每秒10次)之后,其他线程必须停止运行,因此您的线程必须运行以检查条件,当条件大部分为false时,此上下文切换效率较低。

However something smells very fishy in your code, why would you have such code polling when something is initialized? 但是,有些东西在您的代码中闻起来很腥,为什么在初始化某些东西时会有这样的代码轮询? If the initialisation is asynchronous there will already be some notification mechanism, eg a callback, when it is done so the polling is unnecessary. 如果初始化是异步的,那么在完成时将已经有某种通知机制,例如回调函数,因此不需要轮询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM