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

Rare exception in RelayCommand #7644

Open
kant2002 opened this issue Feb 18, 2022 · 7 comments
Open

Rare exception in RelayCommand #7644

kant2002 opened this issue Feb 18, 2022 · 7 comments
Labels

Comments

@kant2002
Copy link
Contributor

Describe the bug
Sometimes RelayCommand crash application with following stack trace.

Unhandled Exception: System.InvalidOperationException: Call from invalid thread
   at Avalonia.Threading.Dispatcher.VerifyAccess() + 0x4c
   at Avalonia.AvaloniaObject.GetValue[T](StyledPropertyBase`1) + 0x2e
   at Avalonia.Controls.MenuItem.CanExecuteChanged(Object, EventArgs) + 0x30
   at System.Reactive.AnonymousSafeObserver`1.OnNext(T) + 0x28
   at System.Reactive.Subjects.FastImmediateObserver`1.EnsureActive(Int32) + 0x334
   at System.Reactive.Subjects.ReplaySubject`1.ReplayBase.OnNext(T) + 0xc0
   at System.Reactive.Linq.ObservableImpl.CombineLatest`3._.SecondObserver.OnNext(TSecond) + 0x7d
   at System.Reactive.Subjects.FastImmediateObserver`1.EnsureActive(Int32) + 0x334
   at System.Reactive.Subjects.ReplaySubject`1.ReplayBase.OnNext(T) + 0xc0
   at System.Reactive.SafeObserver`1.WrappingSafeObserver.OnNext(TSource) + 0x2b
   at System.Reactive.ObserveOnObserverLongRunning`1.Drain() + 0xa6
   at AvaloniaCoreRTDemo!<BaseAddress>+0x1693985
   at AvaloniaCoreRTDemo!<BaseAddress>+0x1693d69

To Reproduce
I do not have reliable repro steps. This is happens occasionally and non-deterministic. It seems to be easier to repro on first or maybe second launch and then cannot repro.

  1. Clone https://github.com/teobugslayer/AvaloniaCoreRTDemo on Linux
  2. Run application using dotnet run
  3. Enter text in text box
  4. Open Help menu
  5. Press Exit. Crash! Boom! Bang! happens here.

Expected behavior
Reliably not crash application.

Desktop (please complete the following information):

  • OS: Linux Gentoo (but seems to be unrelated)
  • Version 0.10.8

Additional context
Add any other context about the problem here.

@kant2002 kant2002 added the bug label Feb 18, 2022
@fitdev
Copy link
Contributor

fitdev commented Sep 15, 2023

Any updates on this? I am getting very similar thing with Avalonia 11. Whenever I call CanExecuteChanged?.Invoke(this, EventArgs.Empty) on my implementation of ICommand. Though in my case it calls into Avalonia.Controls.dll!Avalonia.Controls.Button.CanExecuteChanged(object sender, System.EventArgs e) and throws at Avalonia.Base.dll!Avalonia.Threading.Dispatcher.VerifyAccess.__ThrowVerifyAccess|16_0().

Shouldn't Avalonia take care of automatically delegating all such calls to the UI thread by queuing them up, instead of trying to execute on the calling thread?

@timunie
Copy link
Contributor

timunie commented Sep 18, 2023

No, you need to use Dispather.UiThread.Post if you want to invalidate the command from async task or similar

@fitdev
Copy link
Contributor

fitdev commented Sep 18, 2023

No, you need to use Dispather.UiThread.Post

Is this true of raising CollectionChanged event too? Os is this only particular to ICommand?

@timunie
Copy link
Contributor

timunie commented Sep 18, 2023

All events that should be consumed by the UI. CollectionChanged and also PropertyChanged

@timunie
Copy link
Contributor

timunie commented Sep 18, 2023

@kant2002 can you double-check if the Dispatcher also helps in your situation? If so, we can close this as by design.

@fitdev
Copy link
Contributor

fitdev commented Sep 18, 2023

All events that should be consumed by the UI. CollectionChanged and also PropertyChanged

Thanks for a quick response. This is rather unfortunate, and I am not sure correct. How would any "Observable" Collection (like the built-in System.Collections.ObjectModel.ObservableCollection, or any custom one) know anything at all about the UI thread or Avalonia? They wouldn't - in fact ObservableCollection just simply raises an event whenever it changed, and it is up to the event subscriber, i.e. Avalonia ListBox for example to properly process the event on the correct thread.

Does it then follow that all collection or observable object manipulations that could raise either CollectionChanged or PropertyChanged events subscribed to by Avalonia - would all have to be done on the UI thread? This approach could easily exhaust the UI thread. Wouldn't it be better if Avalonia on some lower level would automatically dispatch processing of such events to the UI thread? Or am I misunderstanding something?

I mean the crux of the matter is that most "observable' objects may not be controllable by the user in as far as "Changed" events they raise, and yet such objects know nothing about the UI thread or Avalonia, so they just do a simple PropertyChanged?.Invoke(...) whenever their internal logic dictates without any regard for threads.

@timunie
Copy link
Contributor

timunie commented Sep 18, 2023

That's why .Add or .Remove should only happen on UiThread. Same for other UI-Libs like WPF. If you look into async collections, I can say that DynamicData (shipped with ReactiveUI) can handle this by .ObserveOn

image

https://www.reactiveui.net/docs/handbook/collections/

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

No branches or pull requests

3 participants