Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Virtualization goes awry during scrolling #8191

Closed
tvass83 opened this issue May 25, 2022 · 4 comments
Closed

Virtualization goes awry during scrolling #8191

tvass83 opened this issue May 25, 2022 · 4 comments

Comments

@tvass83
Copy link

tvass83 commented May 25, 2022

Describe the bug
Scrolling through the items of a ListBox with virtualization on freezes the UI.

To Reproduce
Check the following simple repro app:
https://github.com/tvass83/AvaloniaIssues/tree/main/VirtualizationGoesAwry
OR

<ListBox HorizontalAlignment="Center"
         VerticalAlignment="Center"
         Height="60">
    <ListBoxItem Content="AAA" />
    <ListBoxItem Content="BBB" />
    <ListBoxItem Content="CCC" />
</ListBox>
  1. Use the vertical scrollbar of the ListBox or use the keyboard to navigate through items

Expected behavior
The UI shall not freeze.

Desktop (please complete the following information):

  • OS: Windows 10 version 20H2 (OS build 10.0.19042.804)
  • Avalonia version: observed in 0.10.6.17, but still reproducible in 0.10.14

Additional context
It's not about the UI thread waiting for something to complete, but instead some kind of infinite loop where the hot path is the following:

Avalonia.Base.dll!Avalonia.Utilities.AvaloniaPropertyValueStore`1[System.__Canon]::TryFindEntry 0x0
Avalonia.Base.dll!Avalonia.Utilities.AvaloniaPropertyValueStore`1[System.__Canon]::TryGetValue 0x0
Avalonia.Base.dll!Avalonia.ValueStore::TryGetValue 0x0
Avalonia.Base.dll!Avalonia.ValueStore::TryGetValue 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::GetValueOrInheritedOrDefault 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::GetInheritedOrDefault 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::InheritanceParentChanged 0x0
Avalonia.Base.dll!Avalonia.StyledPropertyBase`1[System.__Canon]::RouteInheritanceParentChanged 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::set_InheritanceParent 0x0
Avalonia.Styling.dll!Avalonia.StyledElement::Avalonia.Controls.ISetInheritanceParent.SetParent 0x0
Avalonia.Controls.dll!Avalonia.Controls.Presenters.ContentPresenter::UpdateChild 0x0
Avalonia.Controls.dll!Avalonia.Controls.Presenters.ContentPresenter::ContentChanged 0x0
Avalonia.Controls.dll!Avalonia.Controls.Presenters.ContentPresenter+<>c::<.cctor>b__17_0 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObjectExtensions+<>c__DisplayClass23_0`1[System.__Canon]::<AddClassHandler>b__0 0x0
System.Reactive.dll!System.Reactive.Subjects.Subject`1[System.__Canon]::OnNext 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::RaisePropertyChanged 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::Avalonia.PropertyStore.IValueSink.ValueChanged 0x0
Avalonia.Base.dll!Avalonia.ValueStore::Avalonia.PropertyStore.IValueSink.ValueChanged 0x0
Avalonia.Base.dll!Avalonia.PropertyStore.BindingEntry`1[System.__Canon]::UpdateValue 0x0
Avalonia.Base.dll!Avalonia.PropertyStore.BindingEntry`1[System.__Canon]::OnNext 0x0
Avalonia.Base.dll!Avalonia.Reactive.BindingValueAdapter`1[System.__Canon]::OnNext 0x0
System.Private.CoreLib.dll!dynamicClass::IL_STUB_MulticastDelegate_Invoke 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::RaisePropertyChanged 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::Avalonia.PropertyStore.IValueSink.ValueChanged 0x0
Avalonia.Base.dll!Avalonia.ValueStore::NotifyValueChanged 0x0
Avalonia.Base.dll!Avalonia.ValueStore::SetExisting 0x0
Avalonia.Base.dll!Avalonia.ValueStore::SetValue 0x0
Avalonia.Base.dll!dynamicClass::IL_STUB_InstantiatingStub 0x0
Avalonia.Base.dll!Avalonia.StyledPropertyBase`1[System.__Canon]::RouteSetValue 0x0
Avalonia.Controls.dll!Avalonia.Controls.Generators.ItemContainerGenerator`1[System.__Canon]::TryRecycle 0x0
Avalonia.Controls.dll!Avalonia.Controls.Presenters.ItemVirtualizerSimple::RecycleContainersForMove 0x0
Avalonia.Controls.dll!Avalonia.Controls.Presenters.ItemVirtualizerSimple::set_OffsetValue 0x0
Avalonia.Controls.dll!Avalonia.Controls.Presenters.ItemVirtualizer::set_Offset 0x0
Avalonia.Controls.dll!Avalonia.Controls.Presenters.ItemsPresenter::Avalonia.Controls.Primitives.IScrollable.set_Offset 0x0
Avalonia.Controls.dll!Avalonia.Controls.Presenters.ScrollContentPresenter+<>c__DisplayClass50_0::<UpdateScrollableSubscription>b__2 0x0
System.Reactive.dll!System.Reactive.AnonymousSafeObserver`1[Avalonia.Vector]::OnNext 0x0
System.Reactive.dll!System.Reactive.Sink`1[Avalonia.Vector]::ForwardOnNext 0x0
System.Reactive.dll!System.Reactive.Linq.ObservableImpl.Skip`1+Count+_[Avalonia.Vector]::OnNext 0x0
Avalonia.Base.dll!Avalonia.Reactive.LightweightObservableBase`1[Avalonia.Vector]::PublishNext 0x0
Avalonia.Base.dll!Avalonia.Reactive.AvaloniaPropertyObservable`1[Avalonia.Vector]::PropertyChanged 0x0
System.Private.CoreLib.dll!dynamicClass::IL_STUB_MulticastDelegate_Invoke 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::RaisePropertyChanged 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::SetAndRaise 0x0
Avalonia.Controls.dll!Avalonia.Controls.Presenters.ScrollContentPresenter::set_Offset 0x0
Avalonia.Controls.dll!Avalonia.Controls.Presenters.ScrollContentPresenter+<>c::<.cctor>b__19_8 0x0
Avalonia.Base.dll!Avalonia.DirectProperty`2[System.__Canon,Avalonia.Vector]::InvokeSetter 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::SetDirectValueUnchecked 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject+DirectBindingSubscription`1[Avalonia.Vector]::OnNext 0x0
Avalonia.Base.dll!Avalonia.Reactive.SingleSubscriberObservableBase`1[Avalonia.Data.BindingValue`1[Avalonia.Vector]]::PublishNext 0x0
Avalonia.Base.dll!Avalonia.Reactive.TypedBindingAdapter`1[Avalonia.Vector]::OnNext 0x0
Avalonia.Base.dll!Avalonia.Reactive.BindingValueAdapter`1[System.__Canon]::OnNext 0x0
System.Private.CoreLib.dll!dynamicClass::IL_STUB_MulticastDelegate_Invoke 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::RaisePropertyChanged 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::SetAndRaise 0x0
Avalonia.Controls.dll!Avalonia.Controls.ScrollViewer::set_Offset 0x0
Avalonia.Controls.dll!Avalonia.Controls.ScrollViewer::set_VerticalScrollBarValue 0x0
Avalonia.Controls.dll!Avalonia.Controls.ScrollViewer+<>c::<.cctor>b__31_18 0x0
Avalonia.Base.dll!Avalonia.DirectProperty`2[System.__Canon,System.Double]::InvokeSetter 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::SetDirectValueUnchecked 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::SetValue 0x0
Avalonia.Base.dll!Avalonia.DirectPropertyBase`1[System.Double]::RouteSetValue 0x0
Avalonia.Markup.dll!Avalonia.Data.TemplateBinding::System.IObserver<System.Object>.OnNext 0x0
Avalonia.Base.dll!Avalonia.Reactive.LightweightObservableBase`1[System.__Canon]::PublishNext 0x0
System.Private.CoreLib.dll!dynamicClass::IL_STUB_MulticastDelegate_Invoke 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::RaisePropertyChanged 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::SetAndRaise 0x0
Avalonia.Controls.dll!Avalonia.Controls.Primitives.RangeBase::set_Value 0x0
Avalonia.Base.dll!Avalonia.DirectProperty`2[System.__Canon,System.Double]::InvokeSetter 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::SetDirectValueUnchecked 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::SetValue 0x0
Avalonia.Base.dll!Avalonia.DirectPropertyBase`1[System.Double]::RouteSetValue 0x0
Avalonia.Markup.dll!Avalonia.Data.TemplateBinding::System.IObserver<System.Object>.OnNext 0x0
Avalonia.Base.dll!Avalonia.Reactive.LightweightObservableBase`1[System.__Canon]::PublishNext 0x0
System.Private.CoreLib.dll!dynamicClass::IL_STUB_MulticastDelegate_Invoke 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::RaisePropertyChanged 0x0
Avalonia.Base.dll!Avalonia.AvaloniaObject::SetAndRaise 0x0
Avalonia.Controls.dll!Avalonia.Controls.Primitives.Track::set_Value 0x0
Avalonia.Controls.dll!Avalonia.Controls.Primitives.Track::ThumbDragged 0x0
Avalonia.Interactivity.dll!Avalonia.Interactivity.Interactive::<AddHandler>g__InvokeAdapter|4_0 0x0
Avalonia.Interactivity.dll!Avalonia.Interactivity.Interactive+<>c__4`1[System.__Canon]::<AddHandler>b__4_1 0x0
Avalonia.Interactivity.dll!Avalonia.Interactivity.EventRoute::RaiseEventImpl 0x0
Avalonia.Interactivity.dll!Avalonia.Interactivity.EventRoute::RaiseEvent 0x0
Avalonia.Interactivity.dll!Avalonia.Interactivity.Interactive::RaiseEvent 0x0
Avalonia.Controls.dll!Avalonia.Controls.Primitives.Thumb::OnPointerMoved 0x0
System.Reactive.dll!System.Reactive.Subjects.Subject`1[System.ValueTuple`2[System.__Canon,System.__Canon]]::OnNext 0x0
Avalonia.Interactivity.dll!Avalonia.Interactivity.EventRoute::RaiseEventImpl 0x0
Avalonia.Interactivity.dll!Avalonia.Interactivity.EventRoute::RaiseEvent 0x0
Avalonia.Interactivity.dll!Avalonia.Interactivity.Interactive::RaiseEvent 0x0
Avalonia.Input.dll!Avalonia.Input.MouseDevice::MouseMove 0x0
Avalonia.Input.dll!Avalonia.Input.MouseDevice::ProcessRawEvent 0x0
Avalonia.Input.dll!Avalonia.Input.InputManager::ProcessInput 0x0
Avalonia.Win32.dll!Avalonia.Win32.WindowImpl::AppWndProc 0x0
Avalonia.Win32.dll!Avalonia.Win32.WindowImpl::WndProc 0x0
Avalonia.Win32.dll!dynamicClass::IL_STUB_ReversePInvoke 0x0
user32.dll!UserCallWinProcCheckWow
user32.dll!DispatchMessageWorker
Avalonia.Win32.dll!dynamicClass::IL_STUB_PInvoke 0x0
Avalonia.Win32.dll!Avalonia.Win32.Win32Platform::RunLoop 0x0
Avalonia.Base.dll!Avalonia.Threading.Dispatcher::MainLoop 0x0
Avalonia.Controls.dll!Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime::Start 0x0
Avalonia.Controls.dll!Avalonia.ClassicDesktopStyleApplicationLifetimeExtensions::StartWithClassicDesktopLifetime 0x0
VirtualizationGoesAwry.dll!VirtualizationGoesAwry.Program::Main 0x0
@tvass83 tvass83 added the bug label May 25, 2022
@maxkatz6
Copy link
Member

Hi! I haven't yet checked the source nor tried to reproduce it. Will try to do it later this week.

But I want to say, that there is no "virtualization" when you use controls source. I.e. when all your items are controls and not models. There is nothing to recycle this way, all items are materialized already, so virtualization is impossible.

@tvass83
Copy link
Author

tvass83 commented May 25, 2022

@maxkatz6 That sounds pretty weird for two reasons:

  1. If I set VirtualizationMode=None on the ListBox then I can't repro anymore
  2. I see the usage of ItemVirtualizerSimple in the callstack

In any case, please give it a try and thanks for picking this up, I really appreciate it!

@maxkatz6
Copy link
Member

Yeah, it seems like a duplicate of this old ticket - #2936

@maxkatz6 maxkatz6 closed this as not planned Won't fix, can't repro, duplicate, stale May 28, 2022
@maxkatz6
Copy link
Member

In general, recommendation to use data bindings so recycling can work properly. Or if there is small number of items and it's just easier to define all items in XAML, then you need to disable virtualization, which is broken, when it's not possible to recycle items.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants