SpinWait vs Sleep waiting. Which one to use?

后端 未结 2 1991
自闭症患者
自闭症患者 2020-11-28 20:09

Is it efficient to

SpinWait.SpinUntil(() => myPredicate(), 10000)

for a timeout of 10000ms

or

Is it more efficient to

2条回答
  •  广开言路
    2020-11-28 20:56

    The best approach is to have some mechanism to actively detect the thing becoming true (rather than passively polling for it having become true); this could be any kind of wait-handle, or maybe a Task with Wait, or maybe an event that you can subscribe to to unstick yourself. Of course, if you do that kind of "wait until something happens", that is still not as efficient as simply having the next bit of work done as a callback, meaning: you don't need to use a thread to wait. Task has ContinueWith for this, or you can just do the work in an event when it gets fired. The event is probably the simplest approach, depending on the context. Task, however, already provides most-everything you are talking about here, including both "wait with timeout" and "callback" mechanisms.

    And yes, spinning for 10 seconds is not great. If you want to use something like your current code, and if you have reason to expect a short delay, but need to allow for a longer one - maybe SpinWait for (say) 20ms, and use Sleep for the rest?


    Re the comment; here's how I'd hook an "is it full" mechanism:

    private readonly object syncLock = new object();
    public bool WaitUntilFull(int timeout) {
        if(CollectionIsFull) return true; // I'm assuming we can call this safely
        lock(syncLock) {
            if(CollectionIsFull) return true;
            return Monitor.Wait(syncLock, timeout);
        }
    }
    

    with, in the "put back into the collection" code:

    if(CollectionIsFull) {
        lock(syncLock) {
            if(CollectionIsFull) { // double-check with the lock
                Monitor.PulseAll(syncLock);
            }
        }
    }
    

提交回复
热议问题