Bug 55433 - No way to properly/fully dispose of all objects or running threads in a page presented with PushModalAsync (Code from dismissed modal pages continues to run)
Summary: No way to properly/fully dispose of all objects or running threads in a page ...
Alias: None
Product: Forms
Classification: Xamarin
Component: Forms ()
Version: unspecified
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Jimmy [MSFT]
Depends on:
Reported: 2017-04-20 16:55 UTC by YLNK
Modified: 2017-06-14 23:26 UTC (History)
2 users (show)

Tags: threading
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description YLNK 2017-04-20 16:55:17 UTC
This one is a little hard to explain and as a note may be somewhat (maybe entirely) related to the bluetooth library I am using which is https://github.com/xabre/xamarin-bluetooth-le

Inside our App class we handle the setup of the bluetooth device, connect to it, and poll the services etc.

Once the device setup is complete, the user may access a new page that is presented with `PushModalAsync`. Inside this page, we subscribe to 2 characteristics of the bluetooth device, which are event handlers that call a function when data is received on one of those channels:

`App._characteristics[1].ValueUpdated -= ReceiveDirectionChange;`
`App._characteristics[0].ValueUpdated -= ReceiveRPMValue;`
`await App._characteristics[1].StartUpdatesAsync();`
`await App._characteristics[0].StartUpdatesAsync();`

The bluetooth device sends data every 500 ms, so these functions fire often.

On this modal page we have an override for `OnBackButtonPressed()`. Inside `OnBackButtonPressed()` we stop the channels from sending data with `StopUpdatesAsync()` and `App._characteristics[1].ValueUpdated -= ReceiveDirectionChange;`. We expect this (particularly the `-=` operation) to remove that event handler and for that function to stop expecting to receive data. After the unsubscribing is complete the function continues on to `return base.OnBackButtonPressed();`

Now, if this modal page is loaded again, and therefore the data channels resubscribed to, we will now start to see symptoms of either that previous modal page not being disposed of properly, or threads still running that are running those event handlers, waiting for data.

If the modal page is loaded 2 times, every 500 ms we will receive the data twice, if that modal page is loaded 6 times, we will receive the data 6 times. There so far has been no way that we can effectively unsubscribe from those event handlers, find the threads causing the issue, stop the threads, or anything other than completely disconnecting from the device, reconnecting and performing setup again (or of course closing the application).

I imagine this is some combination of an issue with Xamarin and the bluetooth library, but is there nothing we can do to ensure everything, including threads waiting for data, is properly disposed of when the modal page is disposed of?
Comment 1 YLNK 2017-04-20 16:56:18 UTC
Sorry I was not sure how to properly format code in the initial comment
Comment 2 YLNK 2017-04-20 17:05:07 UTC
I also forgot to add that despite code still running from the modal pages that were previously disposed of, the Navigation stack is not aware of any modal pages in memory (it reports modal count as 0).
Comment 3 YLNK 2017-04-20 19:01:10 UTC
The code on the pages that have been closed is running to the point where it still attempts to execute functions related to the bluetooth data, except since the objects were mostly disposed of (a timer, an audio player), the functions just crash. There really seems to be no way to stop those old pages from continuously trying to execute code unless the app is completely closed and relaunched.
Comment 4 Jimmy [MSFT] 2017-04-21 16:19:11 UTC
Thank you for filing this report! 

Can you let me know what platform(s) you are experiencing this issue on and which Forms version you are using? If you have not updated to Forms, please do so to verify that the issue still occurs. Can you also confirm that the code in your OnBackButtonPressed() override is being hit when the modal page is being popped? Thanks!
Comment 5 YLNK 2017-04-21 16:57:40 UTC
I'm using VS 2017, the Xamarin version in Help > About is

The Xamarin.Forms nuget package is version

We are experiencing this on Android and iOS. The Android device is running Nougat 7.0. iOS version is 10.3.1, iPhone 5C.

All of the code inside my OnBackButtonPressed() override is hit. The Bluetooth library does some console writes as well to confirm the requests to stop receiving data. The code to remove the event handler is also hit (App._characteristics[1].ValueUpdated -= ReceiveDirectionChange;), but not effective.

Just as a test, in the modal page constructor, I randomized a number between 1-5000 as a makeshift "ID". Then, in the event handlers, when data is received I'm doing "Debug.WriteLine("POSITION 1: " + incomingValue + "    RANDOM ID: " + randID);"

I was able to confirm that every instance of the modal page that is opened, and then closed, is still running through this function, and even in the same order they were opened.
Comment 6 YLNK 2017-04-21 17:00:23 UTC
I also forgot to mention that is I fully disconnect from the bluetooth device, then reconnect before loading that modal page, it does seem to have disposed of those previous pages after that (though having to disconnect and reconnect is not ideal).

I also have an issue report on the bluetooth library's github: https://github.com/xabre/xamarin-bluetooth-le/issues/192
Comment 7 Jimmy [MSFT] 2017-06-14 23:26:47 UTC
Based on the comments in the GitHub issue linked in comment 6, this appears to have been resolved by a change in user code.