question

MattB-4411 avatar image
0 Votes"
MattB-4411 asked ·

UWP: After closing secondary window main app won't return to foreground after backgrounding

It appears that with certain controls as children in a secondary window, once the window is closed and the main app is backgrounded (minimized), the main app will have long and variable delays returning to the foreground after restoring, usually on the order of minutes or even more. This is very easy to reproduce with a SplitView, though I believe other (but not all) controls exhibit this same problem. Currently targeting Platform Version 2004.

Here's a simple class to launch a window, following the basic tutorial for using ApplicationView:

 internal class TestWindow
     {
         private ApplicationView View;
    
         private Window window;
    
         public TestWindow(ApplicationView view)
         {
             View = view;
             View.Consolidated += OnConsolidated;
         }
    
         private void OnConsolidated(ApplicationView sender, ApplicationViewConsolidatedEventArgs args)
         {
             View.Consolidated -= OnConsolidated;
             window.Close();
         }
    
         public static async Task<bool> OpenWindowAsync()
         {
             CoreApplicationView newView = CoreApplication.CreateNewView();
    
             int newViewId = 0;
    
             await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
             {
                 var appView = ApplicationView.GetForCurrentView();
                 var window = new TestWindow(appView);
                 window.window = Window.Current;
                 newViewId = appView.Id;
                 Window.Current.Content = new WindowContent();
    
                 // You have to activate the window in order to show it later.
                 Window.Current.Activate();
             });
    
             var ret = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId);
             return ret;
         }
     }


Here is WindowContent.xaml:

 <Page
     x:Class="Window_Test.WindowContent"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:local="using:Window_Test"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     mc:Ignorable="d"
     Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    
     <SplitView/>
 </Page>


Steps to reproduce:

  1. Open secondary window

  2. Close secondary window

  3. Minimize main window

  4. Restore main window

At this point the main window will not respond to input for some time. It usually will return to normal operation eventually, though this can take many minutes. I can see the EnteredBackground event being triggered (via logs), but the LeavingBackground event does not trigger until just before the main window becomes responsive again.



windows-uwp
· 2
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

At this point the main window will not respond to input for some time. It usually will return to normal operation eventually, though this can take many minutes.

I tried the code you post on my device following the steps. But the app works well when testing. If I bring the main view back to the foreground after closing the secondary view, the main view could respond to my input quickly. So I could not reproduce your issue on my side. Could you reproduce this behavior in another device using the code you post?

Another thing is that why you are creating a window as the secondary view when using ApplicationView class. If you want to create a secondary window, it might be better to use AppWindow Class. For more information please refer to this document: Show multiple views with AppWindow


0 Votes 0 ·

Thanks Roy,

Perhaps there is more to this than just the window configuration. I've created a sample project that reproduces the problem on a few different Windows PCs: https://www.dropbox.com/s/0tkf0ql4r3xsxn2/Window%20Test.zip?dl=0

Could you give this a try? As for why I used the ApplicationView class, at the time some of the limitations of AppWindow made that a less-than-ideal option. If there is no work-around for the above problem then I will have to re-evaluate AppWindow as an option.

0 Votes 0 ·
MattB-4411 avatar image
0 Votes"
MattB-4411 answered ·

I found this Github issue that describes the exact same problem: https://github.com/microsoft/microsoft-ui-xaml/issues/802

It also gives a workaround solution that was not obvious to me and would explain why Roy was unable to reproduce this without a sample app. The issue seems to be caused by the EnteredBackground and LeavingBackground App lifecycle events. My sample used these events for logging purposes. Removing those event handlers seems to resolve the issue. This was especially insidious because it doesn't happen for all controls. I was able to trigger it with a SplitView in the secondary window but not with a handful of other controls I tested. The poster on Github used a ComboBox.

So the best solution at the moment is to remove the EnteredBackground and LeavingBackground handlers.

·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RoyLi-MSFT avatar image
0 Votes"
RoyLi-MSFT answered ·

Hello,

Welcome to Microsoft Q&A!

I could reproduce this issue here. But the result is a little different, when restoring the main view, the app will never respond even waiting for a long time. After testing, the issue is caused by this line of code window.Close();. I'm not sure why I did not reproduce your issue at the first time but your sample did help me to locate the issue.

You could try the following code:

   private void OnConsolidated(ApplicationView sender, ApplicationViewConsolidatedEventArgs args)
         {
             View.Consolidated -= OnConsolidated;
             // window.Close();
             window = null;
         }


Thank you.


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.



· 5 ·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thanks for the suggestions Roy. I tested out a few things and have a couple of observations:

  1. I compared the Window.Current instances from the main window and from the newView thread and they are not the same instance. Additionally, the result of Window.Current.GetHashCode() changes each time it's called from the main window thread. I will post an updated OpenWindowAsync() method in a subsequent comment.

  2. I see memory use grow at a rather rapid pace and never return to a steady state, even after GC. With the test window it appears to be nearly 1MB for each iteration of open/close. It seems the content is leaked if window.Close() is not called so I added window.Content = null to the Consolidated handler. Even with this it seems a thread instance is leaked with each window instance




0 Votes 0 ·

public static async Task<bool> OpenWindowAsync()
{
CoreApplicationView newView = CoreApplication.CreateNewView();
int newViewId = 0;
var currWindow = Window.Current;
Debug.WriteLine(currWindow.GetHashCode()); //<---Changes each time this method is called, unsure why

await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
var appView = ApplicationView.GetForCurrentView();
var window = new TestWindow(appView);
window.window = Window.Current;
newViewId = appView.Id;
Window.Current.Content = new WindowContent();
Debug.WriteLine(Window.Current == currWindow); //false
Debug.WriteLine(Window.Current.GetHashCode());
// You have to activate the window in order to show it later.
Window.Current.Activate();
});
var ret = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId);
return ret;
}


0 Votes 0 ·

I'll try to consult other engineers about this.

0 Votes 0 ·
Show more comments
Heiko-6891 avatar image
0 Votes"
Heiko-6891 answered ·

Should the Close() method be called in the thread of the the secondary window?

Like this:

 private async void PrintPage_Consolidated(ApplicationView sender, ApplicationViewConsolidatedEventArgs args)
 {
     if (PrintPage != null)
     {
         await CoreViewPrint.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
             {
                 CoreWindow.GetForCurrentThread().Close();
                 ApplicationView.GetForCurrentView().Consolidated -= PrintPage_Consolidated;
             });
    
         PrintPage = null;
         CoreViewPrint = null;
     }
 }
· 1 ·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hmm, I made a similar modification to my sample app and it seems to make the problem harder to reproduce, but after about half a dozen repetitions I was able to reproduce the original problem. Given enough time the application does seem to return to normal; in my testing this varies between a few seconds to as long as ten minutes.

0 Votes 0 ·