diff --git a/src/CommunityToolkit.Maui.Camera/Handlers/CameraViewHandler.shared.cs b/src/CommunityToolkit.Maui.Camera/Handlers/CameraViewHandler.shared.cs index a8e76ca734..007f3b1880 100644 --- a/src/CommunityToolkit.Maui.Camera/Handlers/CameraViewHandler.shared.cs +++ b/src/CommunityToolkit.Maui.Camera/Handlers/CameraViewHandler.shared.cs @@ -8,6 +8,9 @@ namespace CommunityToolkit.Maui.Core.Handlers; /// public partial class CameraViewHandler : ViewHandler, IDisposable { + CancellationTokenSource? cts; + bool isDisposed; + /// /// The currently defined mappings between properties on the and /// properties on the . @@ -82,9 +85,29 @@ void Init(ICameraView view) /// protected override async void ConnectHandler(NativePlatformCameraPreviewView platformView) { - base.ConnectHandler(platformView); - - await CameraManager.ConnectCamera(CancellationToken.None); + cts?.Cancel(); + using var newCts = cts = new(); + try + { + base.ConnectHandler(platformView); + await CameraManager.ConnectCamera(newCts.Token); + } + catch (OperationCanceledException) when (newCts.IsCancellationRequested) + { + // Catch and ignore the OperationCanceledException if it was caused by our own cancellation token, + // e.g. the handler is disconnected before the camera connection process completes. + } + catch (Exception) + { + DisconnectHandler(platformView); + } + finally + { + if (cts == newCts) + { + cts = null; + } + } } /// @@ -103,11 +126,20 @@ protected override void DisconnectHandler(NativePlatformCameraPreviewView platfo /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { + if (isDisposed) + { + return; + } if (disposing) { + cts?.Cancel(); + cts = null; + cameraManager?.Dispose(); cameraManager = null; } + + isDisposed = true; } #if WINDOWS