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

Closed
brinko99 opened this issue Jan 27, 2018 · 14 comments
Closed

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

brinko99 opened this issue Jan 27, 2018 · 14 comments

Comments

@brinko99
Copy link

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
Copy link
Contributor

SamBent commented Jan 27, 2018 via email

@brinko99
Copy link
Author

@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 reopened this Jan 30, 2018
@brinko99
Copy link
Author

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

@brinko99
Copy link
Author

brinko99 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
Copy link

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
Copy link

steevcoco 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
Copy link
Contributor

SamBent 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
Copy link

@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
Copy link
Contributor

SamBent 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
Copy link

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

@DarkCloud14
Copy link

It's a long time since the last activity here but there are still issues with the new algorithm even in .NET 4.8, right?

At least we experience an infinite loop/hang issue in an two applications developed for our company and we can only get it fixed by either setting UseLayoutRounding to false for the Grids that are shown if this issue occurs or use the AppContext StarDefinitionsCanExceedAvailableSpace instead.
The Grids have ColumnDefinitions/RowDefinitions and use star sizing at some columns/rows.
We can also switch the scaling from 175% to 150% or 200% to get rid of it but in that case it could happen on another control..

For now we will use the AppContext switch, switching off LayoutRounding isn't an option.
Here is a picture of the call stack when this situation occurs and I pause it.
GridStarHangCallstack

The picture above was taken with dnSpy as the problem is occuring on Surface 4 Pro tablets used in production and I don't have the same tablet at my desk and didn't want to install VS remote debugging tools on one of the affected tablets used in production, at least not yet...

Unfortunately I wasn't able to create an example application that reproduces the problem to upload it here. The only other thing I can say is, that it's not just occurring in the control I took the screenshot with but we also had the problem in a different control at another factory where they use a Dell tablet with 4k resolution and 225% scaling.
All systems with the problem use Windows 10 1809 or newer, I even have the problem on a system that I just updated to Windows 10 1909 and the latest cumulative update for Windows 10 and .NET Framework installed.

The applicaiton currently targets .NET 4.7.2 but after I found this bug report I recompiled the application targeting .NET 4.8 and I still have this problem!

@SamBent
Copy link
Contributor

SamBent commented Nov 21, 2019

@DarkCloud14 - yours looks like a different problem. Your callstack doesn't even mention Grid, but does mention ScrollViewer.OnLayoutUpdated (which this problem didn't). That suggests that the ScrollViewer is getting a constant stream of requests to scroll. The new algorithm is clearly a factor, but is not directly responsible for your hang.

I recommend you open a new issue here (or open a case with CSS if you have a support contract). Attach a repro app if you can. If not, the next best thing would be a TimeTravelDebug trace of a few iterations of the loop.

We've had no reports of any problems with the new algorithm since fixing this one. BTW, the fix was backported to 4.7.x in June - see this announcement.

@DarkCloud14
Copy link

DarkCloud14 commented Nov 21, 2019

@SamBent thanks for the reply and information, you're right, now that I look at it again there isn't any trace of a grid in the callstack.

I think I'll first have a look at the problematic control again as I'm think that we don't have a scrollviewer in use there but use a third party control which internally might have a scrollviewer in use which again it shouldn't use in this case.

The problem that happened at another factory could be different and fixed through the fixes for the grid as we don't use that third party control there but to be sure I would need to get more information like a callstack or use TimeTravelDebug which I didn't know about before, so thanks again for pointing this out.

If I really can't find a solution on our site I try to create a repro app again (or use TimeTravelDebug) and then do one of the steps you mentioned by opening a new issue here or open a case with CSS if we still have an active support contract, I've to check that first...

Also thanks for the info that the fix was backported, I must've overlooked that.

@kalaskarsanket
Copy link
Contributor

This issue has not got any input for long time and we have changed were issues are tracked. If this is still an issue kindly raise a new issue in the appropriate repo as mentioned in dotnet/1275

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants