Phase 2 TestUnlock handshake was synchronous (Thread.Sleep x 8 = 4 s) and the continuation after Phase 1 marshalled back to the WPF dispatcher via the captured SynchronizationContext, so the eight 500 ms sleeps froze the UI right before unlock completed. - UnlockService.RunTestUnlockSequence -> async RunTestUnlockSequenceAsync with Task.Delay(500, ct) and ConfigureAwait(false) - Add ConfigureAwait(false) on every internal await in UnlockService so continuations no longer hop to the UI thread (Task.WhenAll, Task.Delay, connectedTcs, TryFastUnlockAsync, fast-unlock settle delay) - CancellationToken now propagates through Phase 2, so the snackbar Cancel button can interrupt the handshake within 500 ms instead of waiting out all eight Thread.Sleeps Includes the companion observer in IUnlockService / UnlockService (PumpUnlocked event, IsPumpUnlocked, StartObserver/StopObserver) that the Phase 1 wait now races against — lets any source of unlock (fast unlock, external manual, CAN flood finally working) short-circuit the 600 s timer as soon as the CAN TestUnlock parameter confirms it. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
3.0 KiB
3.0 KiB