v0.25.2
What changed and why
A single grab never told the camera to stop.
GrabOnceAsync wrote AcquisitionMode=SingleFrame, issued AcquisitionStart, took its frame and
returned. AcquisitionStart locks AcquisitionMode until AcquisitionStop, and the only
AcquisitionStop calls in the backend were in Close and in StopContinuous (and that one only
when the pump had been running). So the first single grab of a session locked the acquisition mode
for the rest of it, and every grab after that logged a rejected write.
This was reported from a running line with the counts to match: 258 warnings in a day — 260 grabs
minus one first grab per camera — one per inspection grab, making up 69% of the inspection host's log
entries. Judging was unaffected on that day, because the value being written was the one already in
place, so SingleFrame held and all 260 grabs succeeded. The cost was the noise, and this library's
own note on dropped-frame diagnostics says why that matters: a warning that fires all the time stops
anyone reading the warning that counts. It was firing 130 times a day per machine.
There was a heavier branch behind the same lock. StartContinuous sets AcquisitionMode=Continuous
the same way; with the mode locked, that write was rejected, swallowed, and acquisition started
anyway — leaving the device in SingleFrame. It would then send one frame and stop, and the pump's
receive has no deadline (only a cancellation token), so the loop would wait forever: IsGrabbing
stuck at true, frames simply absent, and not one line in the log. The PumpEndedBySelf cleanup
added in 0.25.0 only runs when the loop exits, so it does not help here.
- The single grab now stops acquisition when it is done, in a
finallyso a timed-out or aborted
grab stops the device too — that is exactly when you want it stopped. It does not use the grab's
cancellation token for that. The lock never forms, which closes the continuous branch as well. - A rejected mode change is no longer silent. Setting the mode now reports whether the write was
attempted and refused, and the continuous path logs what follows from it: the camera keeps its
previous mode, so continuous acquisition may deliver one frame and then wait forever. A device with
no such node or entry is not a refusal — it simply does not have the concept — and is not reported.
What was deliberately not done
No deadline was added to the pump's receive. A camera in trigger mode can legitimately go minutes
between frames, so any threshold here would fire on correct setups, and a warning that cries wolf is
worse than no warning. The silence is what was wrong, and the silence is what was fixed. Reading the
mode back before writing it was also declined: it hides the symptom at the cost of a register read
per grab, and the cause is now gone.
Version
0.25.2 — patch. No public API change; one defect fix.
Checks
-
dotnet buildin the default configuration reports 0 warnings -
mainis an ancestor of this branch (the release-pr-guard job verifies it) - the tag will be created on the merge commit,
mainmerged back intodevafterwards, anddevbumped to the next-devversion