Describe the bug 🐞
I have created a minimum reproducible example Avalonia application, which you can access here.
This bug is distinct from #4331, but occurs under similar conditions. It involves the use of SetupDefaultSuspendResume<…>(…), together with a typed suspension host. It occurs when no persisted application state exists, such as on first launch.
When the bug occurs, the following runtime error is raised upon termination of the application:
Exception thrown: 'System.ObjectDisposedException' in System.Reactive.dll.
In addition, the application fails to persist its state.
Step to reproduce
-
Write an implementation of ISuspensionDriver. In my example, my implementation persists to disk the state of the application Model layer via a JSON file. However, the implementation of this interface itself is irrelevant.
-
Create a new Avalonia application. In 'Program.cs', call UseReactiveUI(…). Configure the ReactiveUIBuilder instance using WithAvalonia(), and WithSuspensionHost(…). In my example, I also register with the dependency resolver my implementation of ISuspensionDriver.
- Create some generic Model layer to encapsulate the properties that would be persisted to disk. The contents of the Model are irrelevant. If you are persisting your application state via a JSON file, decorate your properties with
JsonPropertyName(…) attributes.
- If you are persisting your application state via a JSON file, create a
JsonSerializerContext for your Model layer.
- In your
App.axaml.cs file, instantiate AutoSuspendHelper. Next, call OnFrameworkInitializationCompleted() on your AutoSuspendHelper instance.
- Grab a default
ISuspensionHost from RxSuspension.SuspensionHost. Assign a method to its CreateNewAppStateTyped field. Call the typed overload of SetupDefaultSuspendResume<…>(…).
- At this point, if you're using the 'IDisposableAnalyzers' package, you should see some warnings reminding you to dispose of your
AutoSuspendHelper and ISuspensionHost instances. We're gonna dispose of them when the user closes the application. Subscribe to Avalonia's ShutdownRequested event, and call a Dispose() method when the event is fired.
-
Okay, here's the bug. When the AutoSuspendHelper instance is disposed of after the user closes the application, a runtime exception is thrown, and the application fails to persist its state. If you comment out the disposal of these two objects, the bug does not occur. Whew!
-
During your troubleshooting, you might notice that the application state, upon being persisted successfully, is null. Don't worry about this. This behaviour occurs because none of the Model properties have been mutated from their default values, and it's not a ReactiveUI bug.
Reproduction repository
https://github.com/JosiahDanger/SuspensionDisposalBug
Expected behavior
Upon disposal of the AutoSuspendHelper and ISuspensionHost instances at the end of the application lifetime, the System.ObjectDisposedException should not be raised. Furthermore, the application should persist its state successfully.
Screenshots 🖼️
No response
IDE
Visual Studio 2022
Operating system
Windows 11
Version
25H2
Device
No response
ReactiveUI Version
23.2.27
Additional information ℹ️
No response
Describe the bug 🐞
I have created a minimum reproducible example Avalonia application, which you can access here.
This bug is distinct from #4331, but occurs under similar conditions. It involves the use of
SetupDefaultSuspendResume<…>(…), together with a typed suspension host. It occurs when no persisted application state exists, such as on first launch.When the bug occurs, the following runtime error is raised upon termination of the application:
Exception thrown: 'System.ObjectDisposedException' in System.Reactive.dll.In addition, the application fails to persist its state.
Step to reproduce
Write an implementation of ISuspensionDriver. In my example, my implementation persists to disk the state of the application Model layer via a JSON file. However, the implementation of this interface itself is irrelevant.
Create a new Avalonia application. In 'Program.cs', call
UseReactiveUI(…). Configure theReactiveUIBuilderinstance usingWithAvalonia(), andWithSuspensionHost(…). In my example, I also register with the dependency resolver my implementation ofISuspensionDriver.JsonPropertyName(…)attributes.JsonSerializerContextfor your Model layer.App.axaml.csfile, instantiateAutoSuspendHelper. Next, callOnFrameworkInitializationCompleted()on yourAutoSuspendHelperinstance.ISuspensionHostfromRxSuspension.SuspensionHost. Assign a method to itsCreateNewAppStateTypedfield. Call the typed overload ofSetupDefaultSuspendResume<…>(…).AutoSuspendHelperandISuspensionHostinstances. We're gonna dispose of them when the user closes the application. Subscribe to Avalonia'sShutdownRequestedevent, and call aDispose()method when the event is fired.Okay, here's the bug. When the
AutoSuspendHelperinstance is disposed of after the user closes the application, a runtime exception is thrown, and the application fails to persist its state. If you comment out the disposal of these two objects, the bug does not occur. Whew!During your troubleshooting, you might notice that the application state, upon being persisted successfully, is null. Don't worry about this. This behaviour occurs because none of the Model properties have been mutated from their default values, and it's not a ReactiveUI bug.
Reproduction repository
https://github.com/JosiahDanger/SuspensionDisposalBug
Expected behavior
Upon disposal of the
AutoSuspendHelperandISuspensionHostinstances at the end of the application lifetime, theSystem.ObjectDisposedExceptionshould not be raised. Furthermore, the application should persist its state successfully.Screenshots 🖼️
No response
IDE
Visual Studio 2022
Operating system
Windows 11
Version
25H2
Device
No response
ReactiveUI Version
23.2.27
Additional information ℹ️
No response