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

.NET 4.7.1 Grid star sizing causes hang in ResolveStarMaxDiscrepancy #604

Open
brinko99 opened this issue Jan 27, 2018 · 10 comments

Comments

@brinko99
Copy link

commented Jan 27, 2018

I'm seeing another Grid hanging issue in 4.7.1 regarding WPF Grid star sizing column widths.

Specifically ResolveStarMaxDiscrepancy seems to hang or get into some sort of infinite loop under certain conditions. The below Window reproduces the problem; slowly reduce the width of the Window until Column 2 reaches a width of 200 and the application hangs.

@SamBent, you suggest here that a similar issue was resolved in 4.7.1. The workaround mentioned (StarDefinitionsCanExceedAvailableSpace=true) does work around this issue as well.

Breaking the application shows the main thread sitting at: PresentationFramework.dll!System.Windows.Controls.Grid.ResolveStarMaxDiscrepancy(System.Windows.Controls.DefinitionBase[] definitions, double availableSize)

<Window x:Class="GridMinWidthRepo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Height="200" Width="500">
    <Grid Margin="0,20,0,0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100" />
            <ColumnDefinition Width="*" MaxWidth="20" />
            <ColumnDefinition Width="*" MinWidth="200" />
        </Grid.ColumnDefinitions>
        <TextBox Grid.Column="0" HorizontalAlignment="Stretch" />
        <TextBox Grid.Column="2" HorizontalAlignment="Stretch"
                 Text="{Binding RelativeSource={RelativeSource Self}, Path=ActualWidth, Mode=OneWay}"/>
    </Grid>
</Window>
@SamBent

This comment has been minimized.

Copy link
Member

commented Jan 27, 2018

@brinko99

This comment has been minimized.

Copy link
Author

commented Jan 27, 2018

@SamBent Hmm... yes, I believe so.

Here's a short video demonstrating the framework version and issue:
https://drive.google.com/file/d/1lqtf74GKra5hmI-rr8N2n2P3Y6GexDsF/view?usp=sharing

Window 10 Enterprise, 10.0.14393 Build 14393
Visual Studio Pro 2017 15.5.4

This is the loaded System.Core.dll:
C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.ore.dll
4.7.2558.0 built by: NET471REL1

@brinko99 brinko99 closed this Jan 27, 2018

@brinko99 brinko99 reopened this Jan 30, 2018

@brinko99

This comment has been minimized.

Copy link
Author

commented Jan 30, 2018

Must have accidentally closed the issue. It is still relevant....

@brinko99

This comment has been minimized.

Copy link
Author

commented May 4, 2018

I continue to see this issue in the just released 4.7.2. The same behavior is seen as shown in the short video linked to above.

@EamonHetherton

This comment has been minimized.

Copy link

commented Jul 19, 2018

We're seeing what I believe is the same issue.
<AppContextSwitchOverrides value="Switch.System.Windows.Controls.Grid.StarDefinitionsCanExceedAvailableSpace=true" /> resolves the problem but seems like a workaround for a bug rather than a fix. Also we seem to only encounter the issue at 120 DPI.

@steevcoco

This comment has been minimized.

Copy link

commented Sep 27, 2018

I can reproduce this bug reliably in Framework 4.7.2 ... And it was not hard to hit!

I have created a repository on GitHub with a simple project that will reliably hang. It is here:

https://github.com/steevcoco/Net472SetFinalSizeMaxDiscrepancyHangs

... In fact, it requires using a DependencyProperty, which I ONLY used in code (not in XAML --- and it so happens to be defined on a UIElement and not a FrameworkElement; don't know it that also contributes).

@SamBent

This comment has been minimized.

Copy link
Member

commented Oct 5, 2018

@steevcoco - I run your project on 4.7.2 with no problem. Are you running in 120dpi (or other dpi), like @EamonHetherton?

We have fixed two hangs in Grid: one from this report that arises when *-columns with Min constraints use up all the available space, and another that arises only in high dpi when UseLayoutRounding=true and min widths for *-columns cause unfavorable rounding decisions. They have the same callstack, but different root causes; both are fixed in 4.8. EamonHetherton probably hit the second bug, and perhaps you did too.

I doubt that the DP is relevant. More likely by commenting out the DrawingGrid you changed the effective min-widths in a way that produces better rounding decisions. The second bug is highly sensitive - changing any of the widths involved by even a tiny fraction of a pixel can change the rounding decisions and go from hang to no-hang (or vice-versa).

@steevcoco

This comment has been minimized.

Copy link

commented Oct 7, 2018

@SamBent - I CAN 100% reliably crash with that project on this machine ...

There IS display SCALING enabled here: the Windows Text Scaling is set to 116%. This is a 3K display --- 120 dpi, 2880x1620, 60 Hz. And I HAVE just confirmed that disabling the SCALING DOES cure it!

This is a laptop with two display cards; and I'm also reasonably sure I HAVE seen it happen on both display drivers (plugged in and unplugged). It will hang every time.

Please note also: it seems TOUCHY! Previously, I had to ONLY disable the "DrawingGrid" instance that is inside a Border ... But just now I ran again and that didn't work! I have to disable BOTH instances of the "DrawingGrid" to get it to run! (While text scaling is enabled.) --- Disabling Windows Text Scaling seems to let it run normally with both instances in the window.

@SamBent

This comment has been minimized.

Copy link
Member

commented Feb 13, 2019

For the benefit of people with similar problems who get to this issue, here's a summary. For simplicity it refers to 'columns' and 'widths', but everything also applies to 'rows' and 'heights'.

.Net 4.7 included a new algorithm for allocating space to columns in a Grid declared with '*' in their widths. The new algorithm improved over the old one in many ways, chiefly to fix over-allocation: columns receiving so much space that the total width exceeds the width of the Grid itself. The old algorithm is still available; there's an app-context switch that chooses between them:
Switch.System.Windows.Controls.Grid.StarDefinitionsCanExceedAvailableSpace
This defaults to 'false' for apps that target .Net 4.7 and above, and to 'true' for earlier target versions.

Unfortunately the new algorithm had three bugs (that we know of), all resulting in infinite loops.

  1. Two *-columns, both declaring MinWidth and MaxWidth; content doesn't exceed MaxWidth; first MinWidth plus any other fixed or Auto columns exceeds available width. [442027, Issue 393].
  2. The *-columns with min constraints use up all the available space. [560609, Issue 604]
  3. High DPI; UseLayoutRounding is true; *-columns acquire minimum width from a child with ColumnSpan > 1; floating-point roundoff has unfortunate outcome. [619978].

The first bug was fixed in .Net 4.7.1, the other two are fixed in .Net 4.8. If you can't upgrade your .Net runtime, all of them can be avoided using the switch to revert to the old algorithm, although you'd get its bugs as well (such as the over-allocation bug).

The third bug is very sensitive. Changing the widths by a millionth of a pixel can fix the loop (or cause it to happen). Changing the DPI scale can flip the bug. Even running on a different machine can flip the bug, presumably because the floating-point hardware gives slightly different results.

@RickStrahl

This comment has been minimized.

Copy link

commented Feb 15, 2019

@SamBent Thanks for the succinct summary here. That's really helpful and hopefully will make this discoverable. I also wrote up a blog post that chronicles the issue from the Markdown Monster perspective and references this summary.

It would be nice if this could get patched back for 4.7 somehow since that is currently the widest use case for .NET runtime users and way too easy to miss. It'll be a long time before tarrgeting 4.8 for general release applications will be a thing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.