Skip to content

fix(client): avoid blocking SemaphoreSlim.Wait on browser-wasm; remove unused sync locks - #598

Merged
adrianhall merged 3 commits into
CommunityToolkit:mainfrom
adrianhall:chore/597-remove-sync-acquirelock
Nov 5, 2026
Merged

adrianhall merged 3 commits into
CommunityToolkit:mainfrom
adrianhall:chore/597-remove-sync-acquirelock

Conversation

@adrianhall

Copy link
Copy Markdown
Collaborator

Summary

OfflineDbContext.BuildDatasyncOfflineOptions()      (called by PullAsync, and by push via Lazy<OfflineOptions>)
- DisposableLock.AcquireLock()                      -> SemaphoreSlim.Wait()   [UnsupportedOSPlatform("browser")]
+ lock (Lock _optionsLock)                          -> Monitor, fine on single-threaded wasm
    build OfflineOptions once

src/.../Threading/
 ├── DisposableLock.cs         - AcquireLock()          (sync, now unused)
 └── AsyncLockDictionary.cs    - AcquireLock(string)    (sync, now unused)

Evidence

  • Before: BuildDatasyncOfflineOptions() reaches SemaphoreSlim.Wait() (CA1416 flags it with SupportedPlatform=browser; throws on .NET 11 browser-wasm per BuildDatasyncOfflineOptions throws PlatformNotSupportedException on .NET 11 Blazor WebAssembly #574).
    After: no blocking semaphore wait remains in the library.
  • New tests:
    BuildDatasyncOfflineOptions_ReturnsSameInstance:   two calls -> same instance, configurator ran once
    BuildDatasyncOfflineOptions_ConcurrentCalls_BuildOnce: 16 parallel calls -> same instance, configurator ran once
    
  • Full solution dotnet test: all 12 test projects pass (Client: 1445 passed, 0 failed).
  • Not verified on an actual .NET 11 browser-wasm runtime; the repo targets net10.0.

Merge Danger

Door: two-way

Blast Radius: internal client locking

  • _optionsLock and both removed methods are internal; no public API change.
  • Behavioral differences from lock vs SemaphoreSlim: re-entrancy is now allowed (a user's OnDatasyncInitialization that re-enters BuildDatasyncOfflineOptions would recurse instead of deadlock, both are user bugs), and calling it on a disposed context no longer throws from the semaphore.
  • Not addressed here (documented on BuildDatasyncOfflineOptions throws PlatformNotSupportedException on .NET 11 Blazor WebAssembly #574): MD5.HashData in PullRequestBuilder and the sync-over-async in UpdateOperationsQueue().

@adrianhall
adrianhall merged commit 213d6a7 into CommunityToolkit:main Nov 5, 2026
7 checks passed
@adrianhall
adrianhall deleted the chore/597-remove-sync-acquirelock branch November 5, 2026 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant