-
Notifications
You must be signed in to change notification settings - Fork 703
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
Fix issue with exception being thrown during cleanup of NavigationView. #6797
Conversation
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
I am curious: Why is there a need for 's_NavigationViewItemRevokersProperty'? Why can the revokers not be stored in a std::vector on NavigationView? |
I think the original idea is that by attaching these revokers to the NVI the lifetime of the revoker objects would be tied to the NVI and we can set it and forget it. This was the case for multiple years until we identified a problem, the this pointer in the handler could be invalid if the NVI outlives the NavigationView. So we updated this to track the NVI's that have revoker objects set on them so we can clear them when we shut down. Looking closer at this there are definite improvements we can make... I see three strategies
|
RevokeNavigationViewItemRevokers(nvi); | ||
nvi.SetValue(s_NavigationViewItemRevokersProperty, nullptr); | ||
} | ||
catch (...) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we know what was causing the exceptions in the first place?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm currently looking into it, because I'm now able to reproduce the issue. 🙂
Would a Once the NavView is being destroyed, the Is the problem with this approach that the NavView would keep the NVIs alive even if they are removed from the NavView? Does a |
The problem with this approach is that the revoker object being stored in NavigationView will keep the DependencyPropertyChangedCallback object alive even after the associated NVI has been cleaned up, that is until the NavigationView is destructed. |
I think... the event source has a strong reference to the DependencyPropertyChangedCallback object.. does the revoker object? it might only have a weak ref... |
And why is that a problem? Is it because when we then try to revoke the event from the now destroyed NVI we crash? |
It would result in memory growth as the app remains open. If the NavigationView is the top level UI and never gets cleaned up except as a (as it is designed for) then as items get added and removed from the navigation view the application memory would grow. |
Confrimed that the revoker object (usually, and in this case always) has a weak ref to the callback object, so in this case the only down side of this method would be that the vector of revokers will grow for the lifetime of the navigationview. |
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
{ | ||
for (const auto& nvi : m_itemsWithRevokerObjects) | ||
{ | ||
nvi.SetValue(s_NavigationViewItemRevokersProperty, nullptr); | ||
try |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment explaining why this is necessary.
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
When NavigationView is being cleaned up in needs to detatch the event handlers on its children NVI's that are still alive, however if those NVI's have already been cleaned up they can be in a state that SetValue(nullptr) throws an exception, which are not allowed during the NavigationView's destructor.