From 4c64fffc9179a3f729b71f42e6c679ea15e0a1e8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 14 Jan 2026 08:25:08 +0000 Subject: [PATCH 1/2] Initial plan From 710c22c816fddb59a4a9f6191f874063d9f6331b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 14 Jan 2026 08:28:32 +0000 Subject: [PATCH 2/2] Fix race condition in CancelCTS with thread-safe lock Co-authored-by: weiyuanyue <176483933+weiyuanyue@users.noreply.github.com> --- AIDevGallery/Controls/SampleContainer.xaml.cs | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/AIDevGallery/Controls/SampleContainer.xaml.cs b/AIDevGallery/Controls/SampleContainer.xaml.cs index ccd2ac21..bb6b47c5 100644 --- a/AIDevGallery/Controls/SampleContainer.xaml.cs +++ b/AIDevGallery/Controls/SampleContainer.xaml.cs @@ -65,6 +65,7 @@ public List NugetPackageReferences private List? _modelsCache; private WinMlSampleOptions? _currentWinMlSampleOptions; private CancellationTokenSource? _sampleLoadingCts; + private readonly object _ctsLock = new object(); private TaskCompletionSource? _sampleLoadedCompletionSource; private double _codePaneWidth; private ModelType? _wcrApi; @@ -109,16 +110,19 @@ internal static async Task WaitUnloadAllAsync() private void CancelCTS() { - var cts = _sampleLoadingCts; - if (cts == null) + CancellationTokenSource? cts; + lock (_ctsLock) { - return; + cts = _sampleLoadingCts; + _sampleLoadingCts = null; } - _sampleLoadingCts = null; - using (cts) + if (cts != null) { - cts.Cancel(); + using (cts) + { + cts.Cancel(); + } } } @@ -220,9 +224,13 @@ public async Task LoadSampleAsync(Sample? sample, List? models, Wi return; } - _sampleLoadingCts?.Dispose(); - _sampleLoadingCts = new CancellationTokenSource(); - var token = _sampleLoadingCts.Token; + CancellationToken token; + lock (_ctsLock) + { + _sampleLoadingCts?.Dispose(); + _sampleLoadingCts = new CancellationTokenSource(); + token = _sampleLoadingCts.Token; + } // if WCR API, check if model is downloaded foreach (var wcrApi in models.Where(m => m.HardwareAccelerators.Contains(HardwareAccelerator.WCRAPI))) @@ -319,8 +327,11 @@ public async Task LoadSampleAsync(Sample? sample, List? models, Wi finally { _sampleLoadedCompletionSource = null; - _sampleLoadingCts?.Dispose(); - _sampleLoadingCts = null; + lock (_ctsLock) + { + _sampleLoadingCts?.Dispose(); + _sampleLoadingCts = null; + } } NavigatedToSampleLoadedEvent.Log(sample.Name ?? string.Empty);