Skip to content

[Bug]: AutoSuspendHelper Disposal Causes Runtime Exception - State Fails to Persist #4352

@JosiahDanger

Description

@JosiahDanger

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

  1. 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.

  2. 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.

Image
  1. 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.
Image
  1. If you are persisting your application state via a JSON file, create a JsonSerializerContext for your Model layer.
Image
  1. In your App.axaml.cs file, instantiate AutoSuspendHelper. Next, call OnFrameworkInitializationCompleted() on your AutoSuspendHelper instance.
Image
  1. Grab a default ISuspensionHost from RxSuspension.SuspensionHost. Assign a method to its CreateNewAppStateTyped field. Call the typed overload of SetupDefaultSuspendResume<…>(…).
Image Image
  1. 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.
Image Image Image
  1. 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!

  2. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions