diff --git a/src/Controls/src/Core/ImageSource.cs b/src/Controls/src/Core/ImageSource.cs index 63bf8dd978d9..36c0897e629d 100644 --- a/src/Controls/src/Core/ImageSource.cs +++ b/src/Controls/src/Core/ImageSource.cs @@ -11,7 +11,7 @@ namespace Microsoft.Maui.Controls [System.ComponentModel.TypeConverter(typeof(ImageSourceConverter))] public abstract partial class ImageSource : Element { - readonly object _synchandle = new object(); + readonly SemaphoreSlim _cancellationTokenSourceLock = new(1, 1); CancellationTokenSource _cancellationTokenSource; TaskCompletionSource _completionSource; @@ -118,7 +118,7 @@ public static ImageSource FromUri(Uri uri) return FromUri(uri); } - private protected void OnLoadingCompleted(bool cancelled) + private protected async Task OnLoadingCompleted(bool cancelled) { if (!IsLoading || _completionSource == null) return; @@ -127,18 +127,28 @@ private protected void OnLoadingCompleted(bool cancelled) if (tcs != null) tcs.SetResult(cancelled); - lock (_synchandle) + await _cancellationTokenSourceLock.WaitAsync(); + try { CancellationTokenSource = null; } + finally + { + _cancellationTokenSourceLock.Release(); + } } - private protected void OnLoadingStarted() + private protected async Task OnLoadingStarted() { - lock (_synchandle) + await _cancellationTokenSourceLock.WaitAsync(); + try { CancellationTokenSource = new CancellationTokenSource(); } + finally + { + _cancellationTokenSourceLock.Release(); + } } protected void OnSourceChanged() diff --git a/src/Controls/src/Core/StreamImageSource.cs b/src/Controls/src/Core/StreamImageSource.cs index 99aacbcfc74c..d32ce97c2b28 100644 --- a/src/Controls/src/Core/StreamImageSource.cs +++ b/src/Controls/src/Core/StreamImageSource.cs @@ -35,17 +35,17 @@ async Task IStreamImageSource.GetStreamAsync(CancellationToken userToken if (IsEmpty) return null; - OnLoadingStarted(); + await OnLoadingStarted(); userToken.Register(CancellationTokenSource.Cancel); Stream stream = null; try { stream = await Stream(CancellationTokenSource.Token); - OnLoadingCompleted(false); + await OnLoadingCompleted(false); } catch (OperationCanceledException) { - OnLoadingCompleted(true); + await OnLoadingCompleted(true); throw; } return stream; diff --git a/src/Controls/src/Core/UriImageSource.cs b/src/Controls/src/Core/UriImageSource.cs index 1b112069f782..50cd5d8ae3ae 100644 --- a/src/Controls/src/Core/UriImageSource.cs +++ b/src/Controls/src/Core/UriImageSource.cs @@ -56,18 +56,18 @@ async Task IStreamImageSource.GetStreamAsync(CancellationToken userToken if (IsEmpty) return null; - OnLoadingStarted(); + await OnLoadingStarted(); userToken.Register(CancellationTokenSource.Cancel); Stream stream; try { stream = await GetStreamAsync(Uri, CancellationTokenSource.Token); - OnLoadingCompleted(false); + await OnLoadingCompleted(false); } catch (OperationCanceledException) { - OnLoadingCompleted(true); + await OnLoadingCompleted(true); throw; } catch (Exception ex)