问题
Looking at some Apple code sample, I found this:
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
// wait() is used to drop new notifications if old ones are still processing, to avoid queueing up a bunch of stale data.
if metadataObjectsOverlayLayersDrawingSemaphore.wait(timeout: .now()) == .success {
DispatchQueue.main.async {
// Some processing...
self.metadataObjectsOverlayLayersDrawingSemaphore.signal()
}
}
}
Context of the code: This is the delegate method when using video capture to detect a QR code (or any other code). Because it is triggered many times per second (if the camera stays on the same QR code), some kind of timeout is needed.
But how does DispatchSemaphore.wait(timeout: .now())
work? And why check if it is .success
?
回答1:
The purpose is what the comment says:
wait() is used to drop new notifications if old ones are still processing, to avoid queueing up a bunch of stale data.
and it works as follows:
- The semaphore is created with a value of one.
- When
metadataOutput
is called the first time,wait(timeout: .now())
succeeds and decrements the value of the semaphore to zero. The processing of the data begins. - If
metadataOutput
is called again before the processing has completed, the semaphore still has a value of zero. Thenwait(timeout:)
would wait for the semaphore to become positive again, but since the timeout value isnow()
, it fails immediately and returns.timedOut
. The effect is that the incoming data is ignored, themetadataOutput
callback method returns immediately. - When the data processing on the has completed, the semaphore is signaled, which increases the value to one. As a consequence, the next time the callback is called, waiting for the semaphore will succeed and the data is processed again.
So in short:
wait(timeout: .now())
returns.success
if a previously submitted block has signaled completion, in that case a new block is submitted for processing the incoming data.wait(timeout: .now())
returns.timedOut
if a previously submitted block is still running, in that case the incoming data is ignored.
来源:https://stackoverflow.com/questions/49632941/what-is-the-purpose-of-semaphore-waittimeout-now