You trigger one snapshot every few minutes, and the script that takes it sometimes fails to open the camera — then succeeds on the second try. The question is whether to hold the camera open for the life of the program or to open, grab and close for each image. The decision: open once at startup, keep the handle for the whole session, grab on demand, and close when the program exits. Every open repeats device discovery and stream setup, which costs hundreds of milliseconds to a couple of seconds, and the open-close rhythm itself is what creates the intermittent busy-device error. Below: what an open cycle actually re-runs, why the flaky open happens and how to test each cause, the timing arithmetic for both patterns, and a bounded-retry session pattern for the cases where you genuinely must reopen.
Keep the camera open and grab on demand
Opening a camera is not a file open. The SDK finds the device, agrees on a transport configuration and puts the sensor into a known state; closing undoes that work. Doing it once per session instead of once per image removes the cost from every capture and removes the race windows that produce the error that clears on retry. The settings you apply after opening — exposure, region of interest, packet size — also stay put for the session instead of snapping back to defaults.
| Keep open, grab on demand | Open, grab, close each time | |
|---|---|---|
| Time to one stored image | about 0.1 s | about 1.3 s; 4.6 s when a retry hits |
| Exposure, ROI, packet size | set once, holds all session | reset at every open, re-apply each time |
| Intermittent busy-device errors | rare | common — the cycle creates the race |
| Between captures | stream stopped, device held | device released; OS may suspend a USB camera |
| First frame after start | exposure already settled | auto-exposure still converging |
Keep open does not mean streaming around the clock. If the station idles for hours, stop acquisition between captures and leave the device open: the handle stays valid and the next grab restarts the stream in milliseconds. What you must not do is close the device and assume the reopen is free — the reopen path is where both the latency and the flaky errors live. Stopping the stream before any close is its own discipline; the USB camera timeout on reopen: stop acquisition before you close guide shows what happens when that order is skipped.
What one open and close cycle actually re-runs
Break the open into four steps and the cost stops being mysterious:
- Discovery. The SDK enumerates devices — descriptor queries on USB3, a GigE Vision discovery handshake on the network. This is also where a camera that lost power mid-session can power back on but never reappear.
- Stream negotiation. Buffer allocation, payload setup and, on GigE Vision, packet-size agreement with the network card and switch.
- Register state. The camera returns to its default or startup configuration, not to the exposure and ROI you set an hour ago.
- Settle. Auto-exposure and auto-white-balance need a few frames to converge, so captures taken immediately after a fresh open can run dark or shifted in color.
Each open pays all four; each close tears them down again. You will meet the same four steps on every bus the shop sells — USB3, GigE or a structured-light 3D pipeline. The cards below show one camera per bus: a 6 MP USB3 mono camera with a 1/1.8" rolling-shutter sensor, a 2.5 MP GigE color camera with a 1/1.7" global shutter, and a projected structured-light 3D camera. All three re-run discovery, negotiation, register state and settle at each open. A structured-light 3D camera also restarts its projector and depth pipeline, which puts it at the top of the open-cost range.
- Sensor format
- 1/1.8"
- Lens mount
- C-mount
- Sensor format
- 1/1.7"
- Lens mount
- C-mount
- Type
- Stereo / structured light
Browsing area scan cameras or stereo and structured-light 3D cameras in the camera finder, read the interface column before the resolution column — for this decision the bus matters more.
Why the open sometimes fails and the retry succeeds
An open error that clears on the second attempt is nearly always a race: something held the camera for a moment, or the device was mid-transition. Check the causes in this order.
- The last close is still in progress. Stream teardown and handle release run asynchronously, so an immediate re-open can arrive while the device is still busy. Test: millisecond-timestamp your open calls. Failures clustering right after the previous capture, while a fresh process opens fine, means your own close is the blocker.
- Another process is polling or holding the camera. Device viewers, monitoring agents, a second copy of the script — a camera is opened exclusively, so one extra holder breaks the next open. Test: shut everything else down for a shift and compare failure counts.
- USB power management suspended the camera. An idle device can be suspended by the OS, and the next open races its re-enumeration. Test: failures that follow long idle gaps. A powered port or hub, with suspend disabled for that hub, ends them.
- Close out of order. Closing without stopping the stream first, or disposing while a grab is in flight, leaves the SDK or device wedged and hands the mess to the next open. Test: stop acquisition, wait for disposal to finish, then close. If the failures disappear, teardown order was the cause; the camera SDK access violation on close: fix teardown order guide covers the same ordering from the crash side.
- GigE discovery or address mismatch. A camera that comes back on a different subnet after a power event fails discovery until something reconfigures it. Test: do the failures follow power cycles? A persistent IP and a matching subnet make discovery deterministic.
Fix the first two causes and the flaky open usually disappears outright. Whatever race remains gets a bounded retry, and a retry that always succeeds should be treated as a scheduled symptom, not a fix.
The cost of reopen per grab, with the arithmetic
Planning values, typical for current hosts rather than one model's spec sheet: t_open = 1.0 s for discovery plus stream start (0.5-2 s across USB3 and GigE Vision setups), t_close = 0.2 s, t_grab = 0.1 s — one frame at 30 fps is 1/30 s ≈ 33 ms, and 0.1 s adds transfer and save margin.
Worked example, one station: a snapshot every 30 s across an 8 h shift of 28,800 s gives N = 28,800 / 30 = 960 captures.
- Keep open: 960 × 0.1 s = 96 s of grab work, plus 1.0 s + 0.2 s = 1.2 s once at startup — about 1.6 min for the shift.
- Reopen each time: 960 × (1.0 + 0.1 + 0.2) = 960 × 1.3 s = 1,248 s, which is 20.8 min of pure open-close overhead.
- Flakiness included: if 1 open in 10 hits the busy error and a 2 s backoff clears it, F = 96 and the shift gains 96 × 2 s = 192 s, landing at 1,248 + 192 = 1,440 s — 24 min. Each unlucky capture takes 1.3 + 2 + 1.3 = 4.6 s instead of 0.1 s, 46× slower.
The decision falls out directly: if a trigger must produce a stored image in under 1 s, the reopen pattern misses on a good day (1.3 s) and badly on a bad one (4.6 s), while the armed session passes with a ten-fold margin.
The session pattern: open once, grab on demand, bounded retry
- Open once at startup, on the host that owns the camera, and log how long the open took — that number is your t_open.
- Apply settings once after the open: exposure, ROI, pixel format and, on GigE, packet size. Never inside the per-capture path.
- Start acquisition and leave it armed. Each capture is then a grab or a software trigger; the software trigger image timeout: why one-shot capture misses frames guide explains why an unarmed stream is what makes one-shot captures time out.
- Retry boundedly on failure: three attempts with backoff starting at 0.5 s and doubling to a 2.0 s cap — 3.5 s worst case — then alert and stop the process. A station that cannot see must stop, not pass parts uninspected.
- Keep one owner. Everything else that wants an image asks the owner process; nobody else opens the device.
- Close in a finally block: stop acquisition, wait for disposal, release the device.
- Watch a heartbeat. A grab counter or a periodic test grab catches a silent stall long before an operator does. The keep a camera open and ready between MQTT-triggered grabs guide runs this pattern in its always-on, message-driven form; when a device really does vanish, the GigE camera disconnected detection: fail fast instead of freezing guide covers alerting instead of hanging.
# Illustrative pseudocode: the call names are generic, your SDK names them differently.
max_attempts = 3 # int, tries before the alert fires
backoff_s = 0.5 # float, seconds; doubles per retry, capped at 2.0
cam = device_open() # once, at program start
apply_settings(cam) # exposure, ROI, packet size: once per session
stream_start(cam) # acquisition armed and left armed
on each capture request:
frame = None # image or None
tries = 0
while frame is None and tries < max_attempts:
frame = grab(cam) # armed stream: returns in about one frame time
if frame is None:
wait(backoff_s) # 0.5, then 1.0, then 2.0 s
backoff_s = min(backoff_s * 2, 2.0)
tries = tries + 1
if frame is None:
alert_and_stop() # fail loud: no uninspected parts pass
Prove it on your own host: millisecond timestamps around open, grab and close, run for one shift. The keep-open log shows the open once and trigger-to-image near 0.1 s on every line. The reopen log shows a 1-2 s open before every capture and, on the unlucky ones, 3.5 s of backoff (0.5 + 1.0 + 2.0) before the retry that works.
Hardware-wise, the pattern wants a host that stays up. A vision controller such as the MV-VC3301H-128G66 puts the camera ports, the light outputs and the runtime license in one fanless box — Intel Core i3 i3-8100, 8 GB of memory, 5+ LAN ports, 4 built-in light channels, VM6200Pro runtime included.
- LAN ports
- 5+ LAN ports
- USB 3 ports
- 3-4 USB 3 ports
- Light outputs
- 4 built-in channels
- Memory
- 8 GB
When reopening each grab is the right call
Four cases, four decisions:
- Another program must own the camera. Your tool should not fight it with retries: ask the owner for images or schedule access. Reopening per grab is the wrong answer to contention.
- Power budget rules. On battery or solar, stop acquisition for the idle hours and let the OS suspend the device — then budget the reopen cost from the arithmetic above and test that path, because a suspended camera re-enumerates on the next open.
- The host reboots nightly. Open once per process at boot. That is still open-once, not open-per-grab.
- The camera sits in a shared bench tool where another user may claim it at any moment. Reopen per grab with the bounded retry, and re-apply or reload your settings after every open.
The trade-off is not camera-specific: the same question comes up on other buses, and the reference on why some programs open and close a serial port for each Modbus read lands on the same answer for serial devices.
Prevention checklist
Run down this list once per station; each item closes one of the failure doors above.
- Open once per process, and close inside a try/finally so a crashed run still releases the device.
- Stop acquisition before every close, and wait for disposal to finish before the program exits.
- Set exposure, ROI, pixel format and packet size once per session, right after the open.
- One owner process per camera; every other tool requests images from it.
- Millisecond timestamps on open, grab and close, kept for at least a shift — the log that finds a race costs one line of code.
- Bounded retry with an alert-and-stop on the final attempt, never an endless retry loop.
- A powered USB port or hub for the camera, with suspend disabled for that hub when captures follow idle gaps.
- On GigE: a persistent IP, camera and network card on one subnet, one agreed packet size.
- A grab-counter heartbeat with an alert, so a stalled session is a message, not a mystery.
If a flaky open survives all of that, the log is the ticket: send it through the contact page and we will help you read it. The systems guides hub collects the grab-loop, trigger and teardown guides in one place for the deeper session design.
Questions
How much faster is a grab on an open camera than an open-grab-close cycle?
On the planning numbers in this guide, a grab on an armed camera returns in about 0.1 s, while open, grab and close takes about 1.3 s — roughly 13 times longer. Measure the open once in your own code, because interface and host load move it; the grab side stays near one frame time, 1/fps, so 33 ms at 30 fps.
Why does the second attempt succeed where the first open failed?
The blocking condition is short-lived: the previous close is still tearing down, a polling tool has just released the device, or a suspended USB camera has finished re-enumerating. A bounded backoff rides out all three, which is why the retry works. Log the failures anyway — a pattern in their timing points at the race you can actually remove.
Can two programs use the same camera at the same time?
Usually no. Machine-vision SDKs open a device exclusively, so a second open fails until the first holder releases it. Keep one owner process and serve images or results to everything else, or check whether your SDK ships a gateway service that brokers several clients before you design a system around retries.
Does a camera that stays open all day overheat or wear out?
An open camera with acquisition stopped sits near standby power. Heat comes from sustained streaming, onboard processing and the illumination running alongside it, not from holding the handle. For an idle station, stop the stream and keep the device open, and power the camera from a powered USB port or its own supply rather than an unpowered hub.
How do I keep exposure, ROI and packet size across a reopen?
Treat every open as a fresh start and re-apply after opening. The clean route is to save your working settings into the camera's flash as a user set once, then load it immediately after each open — in GenICam terms, the UserSetLoad feature — and confirm by reading back ExposureTime, Width and Height before the first grab.
Should the camera be closed when my script finishes?
Yes, cleanly and in order: stop acquisition, wait for the disposal call to complete, then release the device — ideally in a try/finally so a crashed run still closes it. A program that dies mid-stream can leave the handle held until the OS cleans up, and that stale hold is what makes the next program's first open fail.



