Share via

LayoutCycleException on closing a window

Heiko 1,311 Reputation points
2021-01-08T17:43:22.943+00:00

Hello,

Some user installations seem to crash with a LayoutCycleException. I myself had the problem during the development of the app, but cannot reproduce it anymore.

I have a MainPage where I open another window like this:

private async void buttonPrint_Click(object sender, RoutedEventArgs e)
{
    int printWindowId = -1;

    CoreViewPrint = CoreApplication.CreateNewView();

    await CoreViewPrint.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            CoreWindow  coreWindow = CoreWindow.GetForCurrentThread();
            Frame       frame = new Frame();

            ApplicationView.GetForCurrentView().Consolidated += PrintPage_Consolidated;
            printWindowId = ApplicationView.GetApplicationViewIdForWindow(coreWindow);
            frame.Navigate(typeof(PrintPage));
            Window.Current.Content = frame;
            Window.Current.Activate();
            ApplicationView.GetForCurrentView().Title = AppStrings.Printing;
        });

    await ApplicationViewSwitcher.TryShowAsStandaloneAsync(printWindowId, ViewSizePreference.UseMore, ApplicationView.GetForCurrentView().Id, ViewSizePreference.Default);
}

I can now resize the new window with the PrintPage as I like. Its content will be adjusted continuously.

However, if the user presses the X in the upper right corner of the title bar to close the window, there is a crash with a LayoutCycleException in some installations. When the X is clicked, the UWP runtime sets the PrintPage window size to the size of the MainPage. In the SizeChanged handler of the PrintPage, I can't detect if the X was clicked. I guess that the processing in the SizeChanged handler after the X is clicked is causing the crash.

Furthermore, I noticed that after closing the PrintPage (if the app didn't crash), any resizing of the MainPage triggers a SizeChanged event of the PrintPage. I think this is a bug in the runtime. In the PrintPage, I notice in the SizeChanged handler that the PrintPage is still visible even though it is not. Therefore, I now remove the SizeChanged handler of the PrintPage in the Consolidated handler. This mitigates this bug.

However, the crash occurs right when I click on the X of the PrintPage. Does anyone know how I can fix this problem?

PS: When I debug with F5, there is another problem: If I click on the X in the PrintPage, its entire content is moved to the MainPage window. The window of the PrintPage is closed. The content of the MainPage is gone. Instead, the PrintPage is displayed in the MainPage window.

(VS 2017)

Developer technologies | Universal Windows Platform (UWP)
0 comments No comments

Answer accepted by question author

Yan Gu - MSFT 2,681 Reputation points
2021-01-11T05:39:16.373+00:00

Hello,

Welcome to Microsoft Q&A.

I cannot reproduce the situation that there is a crash with a LayoutCycleException when a user presses the X in the upper right corner of the new window. But I reproduce the second situation that the PrintPage is displayed in the MainPage window after clicking the X in the new PrintPage window when debugging with F5.

You need to call the CoreWindow.Close method to exit the message loop in the Consolidated event handler.

Please check the following code:

CoreWindow coreWindow;  
  
private async void Button_Click(object sender, RoutedEventArgs e)  
{  
    printWindowId = -1;  
    var CoreViewPrint = CoreApplication.CreateNewView();  
    await CoreViewPrint.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async() => {  
        coreWindow = CoreWindow.GetForCurrentThread();  
        var applicationView = ApplicationView.GetForCurrentView();  
        Frame frame = new Frame();  
        applicationView.Consolidated += ApplicationView_Consolidated;  
        printWindowId = ApplicationView.GetApplicationViewIdForWindow(coreWindow);  
        frame.Navigate(typeof(PrintPage));  
        Window.Current.Content = frame;  
        printPageFrame = frame;  
        Window.Current.Activate();  
        applicationView.Title = "I am a title";  
        var inner = Window.Current;  
    });  
    await ApplicationViewSwitcher.TryShowAsStandaloneAsync(printWindowId, ViewSizePreference.UseMore,  
        ApplicationView.GetForCurrentView().Id, ViewSizePreference.Default);  
}  
  
private void ApplicationView_Consolidated(ApplicationView sender, ApplicationViewConsolidatedEventArgs args)  
{  
    if (coreWindow != null)  
    {  
        coreWindow.Close();  
    }  
}  

By adding the above code, you could test the SizeChanged event handler of PrintPage will not be trigger when you resize the size of MainPage window after closing the new PrintPage window. And, the content of MainPage window will not be replaced with the PringPage after closing the new created PrintPage window when debugging with F5.

Please tell me whether the situation that there is a crash with a LayoutCycleException when a user presses the X in the upper right corner of the new window will happen in your side when you using the above code.

Update:

Based on the document, we know that when we have the main view and the secondary view and clicking the close(X) button in the window title bar of the main view(MainPage), the main view’s window is hidden and its thread remains active. So the SizeChanged event handler of MainPage and the SizeChanged event handler of PrintPage will all be called when you close the MainPage window and resize the PrintPage window. Calling Close method on the main view’s window causes an InvalidOperationException to occur. If the main view’s thread is terminated, the app closes. Therefore, the better way is to use Application.Exit to close the whose app without leaving the PrintPage still shown.

If you want to close the secondary view(PrintPage), you need to call the Close() to release the window resource in the Consolidated event handler or other location before the window is closed by clicking the X icon.

I didn’t reproduce the situation that the SizeChanged event is fired before the Consolidated event. My SizeChanged event handlers are added by using the code Window.Current.SizeChanged += Current_SizeChanged; in the constructor of MainPage and PrintPage.

You could try to use another event SystemNavigationManagerPreview.CloseRequested event to replace the Consolidated event to see if it can resolve your problem. Note the necessary capability.


If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

Was this answer helpful?

1 person found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. Heiko 1,311 Reputation points
    2021-01-11T15:57:42.003+00:00

    Thank you very much for your reply.

    I can confirm that the SizeChanged events are no longer fired when Close() is called.

    However, I have the same problem that in the MainPage the SizeChanged events are fired if I closed the MainPage before the PrintPage. With the following code I tried to suppress the SizeChanged events in the MainPage:

    internal void SetMainPage(MainPage mainPage)
    {
        MainPage = mainPage;
        MainPage.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                ApplicationView.GetForCurrentView().Consolidated += MainPage_Consolidated;
            });
    }
    
    private void MainPage_Consolidated(ApplicationView sender, ApplicationViewConsolidatedEventArgs args)
    {
        MainPage.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
            //  CoreWindow.GetForCurrentThread().Close();   // => COMException
                ApplicationView.GetForCurrentView().Consolidated -= MainPage_Consolidated;
                MainPage = null;
            });
    }
    

    Unfortunately, when I call 'CoreWindow.GetForCurrentThread().Close()' I get a COMException (0x8000000E) with the text

    "A method is called at an unexpected time. Closing main window is not allowed."

    Every time I resize the PrintPage that is still open, the SizeChanged events of the closed MainPage are now fired. So after the Consolidated event has fired for the MainPage, I now ignore all SizeChanged events in the MainPage.

    During debugging with F5, when the MainPage is closed, the MainPage is moved to the PrintPage window and the PrintPage is no longer visible.

    That is one problem.

    The actual problem why I created this thread is that while closing a window via the X in the title bar, the SizeChanged event is fired. This SizeChanged event fires before the Consolidated event, so I can't detect that the user is closing the window. I suspect that handling the SizeChanged event at that moment, when the user closes the window, will cause a LayoutCycleException on some installations.

    The SizeChanged event is triggered when you click the X only if you have previously resized the window.

    1) Open PrintPage.
    2) Change PrintPage size.
    3) Close PrintPage.
    4) PrintPage.SizeChanged is triggered.

    or

    1) Open PrintPage.
    2) Change PrintPage size.
    3) Close MainPage.
    4) MainPage.SizeChanged is triggered.

    However, it is also possible that the SizeChanged event and the SizeChanged handler has nothing to do with the LayoutCycleException and that this exception also occurs if the sizes of the windows are not changed. The LayoutCycleException simply occurs when closing the PrintPage. I will try to reproduce the exception again.

    Was this answer helpful?


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.