Cysharp / Cysharp/ObservableCollections

App crashes on rapid async updates when using ToNotifyCollectionChanged with WinUI 3 ListView

Open
#115 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
1k
Forks
73
Avg merge
5d 4h
Merged PRs (30d)
2

Description

Description

When using ToNotifyCollectionChanged to bind an ObservableList to a WinUI 3 ListView, the application crashes with an ArgumentOutOfRangeException during rapid asynchronous updates (e.g., inside Task.Run).

Observed Behavior
  • The application terminates immediately with a specific exception during collection synchronization.
  • Crucially, while CollectionChanged is subscribed to log the action, only the Add action is ever logged before the process crashes. The subsequent Remove action is never reached/logged.
  • This crash does not occur if the same operations are performed directly on the UI thread (without Task.Run).
Exception

System.ArgumentOutOfRangeException: This collection cannot work with indices larger than Int32.MaxValue - 1 (0x7FFFFFFF - 1). (Parameter 'index')

Stack Trace
   at ABI.System.Collections.IList.ToAbiHelper.EnsureIndexInt32(UInt32 index, Int32 listCapacity)
   at ABI.System.Collections.IList.ToAbiHelper.GetAt(UInt32 index)
   at ABI.System.Collections.IList.Do_Abi_GetAt_0(IntPtr thisPtr, UInt32 index, IntPtr* result)
--- End of stack trace from previous location ---
   at WinRT.ExceptionHelpers.<ThrowExceptionForHR>g__Throw|38_0(Int32 hr)
   at WinRT.ExceptionHelpers.ThrowExceptionForHR(Int32 hr)
   at ABI.System.Collections.Specialized.NotifyCollectionChangedEventHandler.NativeDelegateWrapper.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
   at ObservableCollections.FiltableSynchronizedViewList`2.RaiseChangedEvent(NotifyCollectionChangedEventArgs e)
   at ObservableCollections.CollectionEventDispatcherEventArgs.Invoke()
   at ObservableCollections.SynchronizationContextCollectionEventDispatcher.SendOrPostCallback(Object state)
   at Microsoft.UI.Dispatching.DispatcherQueueSynchronizationContext.<>c__DisplayClass2_0.<Post>b__0()
Reproducible Code
<Window
    x:Class="ObservableCollectionsTests.MainWindow"
    xmlns="[http://schemas.microsoft.com/winfx/2006/xaml/presentation](http://schemas.microsoft.com/winfx/2006/xaml/presentation)"
    xmlns:x="[http://schemas.microsoft.com/winfx/2006/xaml](http://schemas.microsoft.com/winfx/2006/xaml)">
    <StackPanel>
        <Button Content="Trigger Crash" Click="Button_Click"/>
        <ListView ItemsSource="{x:Bind List}" />
    </StackPanel>
</Window>
using Microsoft.UI.Xaml;
using ObservableCollections;
using System.Diagnostics;
using System.Threading.Tasks;

namespace ObservableCollectionsTests;

public sealed partial class MainWindow : Window
{
    private ObservableList<string> _ol = [];
    public INotifyCollectionChangedSynchronizedViewList<string> List;

    public MainWindow()
    {
        this.List = this._ol.CreateView(x => x).ToNotifyCollectionChanged(SynchronizationContextCollectionEventDispatcher.Current);
        
        this.List.CollectionChanged += (s, e) => {
            Debug.WriteLine(e.Action);
        };
        
        InitializeComponent();
    }

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        await Task.Run(() =>
        {
            this._ol.Add("1");
            this._ol.RemoveAt(0);
        });
    }
}

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the WinUI 3 reproduction in MainWindow with ToNotifyCollectionChanged and SynchronizationContextCollectionEventDispatcher.Current, then inspect the dispatcher and collection synchronization path implicated by the stack trace. Done means rapid background Add and RemoveAt operations no longer terminate the app and both collection-change actions can be observed.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
desktop
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.