dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.26k stars 1.76k forks source link

Blazor MAUI Hybrid Application Reload/Refresh after some time [MacOS] #24669

Open dhruvindudhat opened 2 months ago

dhruvindudhat commented 2 months ago

Description

I have Blazor Maui Hybrid app for mac catalyst. When I run the application in mac catalyst it will refresh/reload it self after some time[refresh time is not fix refresh will occurs anytime]. Due to reload i lost all the progress which I have made in application and it will easily reproducable. I have attached link for minimal solution. Please review and tell me the workaround or fix to prevent this unnecessary relaod. I am not sure what is the cause is it either webview or maui application?

Steps to Reproduce

  1. Run the attached project
  2. Click on "Counter" from navigation. click on "Click Me" button. -> One Loader will be displayed.
  3. Wait for around half an hour or more time (minimize the running application)
  4. Come back to application and you will notice that application is refreshed and loader will be gone....

Link to public reproduction project repository

https://github.com/dhruvindudhat/Demo

Version with bug

Unknown/Other

Is this a regression from previous behavior?

No, this is something new

Last version that worked well

Unknown/Other

Affected platforms

macOS

Affected platform versions

No response

Did you find any workaround?

No response

Relevant log output

No response

github-actions[bot] commented 2 months ago

Hi I'm an AI powered bot that finds similar issues based off the issue title.

Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you!

Closed similar issues:

Note: You can give me feedback by thumbs upping or thumbs downing this comment.

ninachen03 commented 2 months ago

I cannot repro this issue at maccatalyst platform on the latest 17.6.14 (build 413).and my MAC is M2

dhruvindudhat commented 2 months ago

@ninachen03 Have you tried with attached solution?

dhruvindudhat commented 2 months ago

I have also tried with latest 17.6.14 (build 413) and Mac Mini with Mac OS 14.2.1.Project is in .net 6.0 but still I got the same issue. can you recheck?

ninachen03 commented 2 months ago

@dhruvindudhat I use the demo and change the NET From 6.0 to 8.0. please use the latest to try it.

drasticactions commented 2 months ago

@dhruvindudhat

Your repro project is running an out of support version of .NET and .NET MAUI, https://github.com/dhruvindudhat/Demo/blob/main/Demo/Demo.csproj#L4-L5

You should upgrade to at least .NET 8.0 and try it there first.

dhruvindudhat commented 2 months ago

@drasticactions I have tried with .net 8 but still facing same issue in demo project

mattleibow commented 2 months ago

@Eilon thoughts?

dhruvindudhat commented 2 months ago

My actual project has this issue in 8GB RAM Mac but it is working fine in 16GB mac!! Is this regarding WKWebview Memory Leak??

mattleibow commented 2 months ago

@jonathanpeppers what is the best way to check if this is memory related? I suppose the easiest is to open the Activity Monitor and see if usage is increasing over time? But then maybe a GC dump of some sort?

@Eilon is there some event to watch to track reload events? Maybe an event for navigating/navigated and then that can be logged to see when that is happening?

@dhruvindudhat maybe you could attach a screen recording of what you are seeing? Also, maybe check the safari developer tools and see if there is something there?

jonathanpeppers commented 2 months ago

I wouldn't think there is a memory issue here. It's not a complex JavaScript "game" that would use a lot of memory in the browser, right? Activity Monitor, Instruments, would be good enough to check regular memory usage.

I think this more likely the OS does something to the webview control when the app is minimized for a while.

dhruvindudhat commented 2 months ago

@jonathanpeppers This indicates, The issue is not related to memory and I just notice app is using only 120 MB in Activity Manager. Looks your point regarding OS is Possible!

After half an hour application is refreshed automatically and due to refresh I got attached error in Inspector[Please see below attached image].

Screenshot 2024-09-16 at 9 53 34 AM

Also I observe that if there is no datagrid in page content and refresh/reload happens then there is no exception occurs only refresh happens and user redirect to home page.

I also capture the screen shot of memory usage from activity monitor of the application which runs long process of pdf generation and this shows huge memory leakage.

Screenshot 2024-09-16 at 9 54 03 AM 1

Sometimes this refresh occurs within five minutes of application run. If I don't do anything after first refresh and put machine in ideal condition then webview is refreshed itself so many times with interval of 5-10 minutes.

jinge1936 commented 2 months ago

Have faced same issue, tried with electron+react and maui hybrid. Honestly , electron is much stable.

mattleibow commented 2 months ago

I wonder if there is a way to tell the os to keep the app alive... This may use more power, so maybe electron just ignores that and keeps everything in memory and alive...

We do have an essentials api to keep the screen on that you can try: https://learn.microsoft.com/en-us/dotnet/api/microsoft.maui.devices.devicedisplay.keepscreenon?view=net-maui-8.0

This may be overly aggressive, but might help until you are able to find out the correct way to keep you apps alive even when minimized.

@Eilon @drasticactions any ideas as to prevent the os from releasing the webview in a minimized app?

dhruvindudhat commented 2 months ago

@mattleibow I have tried your solution with putting DeviceDisplay.KeepScreenOn =true but still application is refreshed itself.

mattleibow commented 2 months ago

I asked copilot how to prevent my macos app from being suspended when minimized and it recollended this:

// In your MAUI Blazor Hybrid project, create a new file: MacOSAppService.cs
#if MACCATALYST
using Foundation;

public class MacOSAppService
{
    NSObject activity;

    public void PreventAppSuspension()
    {
        NSProcessInfo.ProcessInfo.DisableAutomaticTermination("Preventing app suspension");
        NSProcessInfo.ProcessInfo.DisableSuddenTermination();
        activity = NSProcessInfo.ProcessInfo.BeginActivity(NSActivityOptions.UserInitiated, "Preventing App Nap");
    }

    public void AllowAppSuspension()
    {
        NSProcessInfo.ProcessInfo.EnableAutomaticTermination("Preventing app suspension");
        NSProcessInfo.ProcessInfo.EnableSuddenTermination();
        if (activity != null)
        {
            NSProcessInfo.ProcessInfo.EndActivity(activity);
            activity = null;
        }
    }
}
#endif

And to use it:

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
            });

        #if MACCATALYST
        builder.Services.AddSingleton<MacOSAppService>();
        #endif

        return builder.Build();
    }
}

And then

public partial class App : Application
{
    private readonly MacOSAppService _macOSAppService;

    public App(MacOSAppService macOSAppService)
    {
        InitializeComponent();
        MainPage = new MainPage();
        _macOSAppService = macOSAppService;
    }

    protected override Window CreateWindow(IActivationState activationState)
    {
        var window = base.CreateWindow(activationState);

        window.Created += OnWindowCreated;
        window.Activated += OnWindowActivated;
        window.Deactivated += OnWindowDeactivated;
        window.Stopped += OnWindowStopped;
        window.Resumed += OnWindowResumed;

        return window;
    }

    private void OnWindowCreated(object sender, EventArgs e)
    {
        _macOSAppService?.PreventAppSuspension();
    }

    private void OnWindowActivated(object sender, EventArgs e)
    {
        _macOSAppService?.PreventAppSuspension();
    }

    private void OnWindowDeactivated(object sender, EventArgs e)
    {
        _macOSAppService?.AllowAppSuspension();
    }

    private void OnWindowStopped(object sender, EventArgs e)
    {
        _macOSAppService?.AllowAppSuspension();
    }

    private void OnWindowResumed(object sender, EventArgs e)
    {
        _macOSAppService?.PreventAppSuspension();
    }
}

Keep in mind this may keep the CPU awake and consuming power

drasticactions commented 2 months ago

Looking through the comments here, I am unsure if there is enough to say if this is a MAUI bug, or an issue with how you designed your application. That it's using approximately 13 GBs of ram seems bad and that requires more investigation. I don't think hacking your application to not unload the web view will help much.

FWIW I tried your sample, in Release mode unattached to a debugger, left it on overnight, minimized, and it was still running when I went back to my Mac. Unless someone else can repro this based on your sample, I have a feeling you're having other issues with your application.

dhruvindudhat commented 2 months ago

@mattleibow I add your given code but , NSProcessInfo.ProcessInfo.DisableAutomaticTermination("Preventing app suspension"); NSProcessInfo.ProcessInfo.DisableSuddenTermination();

This methods are not there in the ProcessInfo Class? Any guesses?

dhruvindudhat commented 2 months ago

@drasticactions did you try this? On Counter page click the button. it will open one kind of dialog which has loader gif. Then leave machine in ideal mode or minimize the app. when you open again after some time that page has been refreshed and loader will be no longer there [Loader added due to identify that application is still in the previous state or not] Even when you add logs in OnInitialized() method you will get logs also for new initialisation when reload occurs.

dhruvindudhat commented 1 month ago

@mkArtakMSFT It is very urgent to get fix this. Please try to give workaround so we can proceed for successful release and later will upgrade to .net 10 or above once release done.

sonali-vaghela commented 1 month ago

I am facing the same issue. Is there any workaround?

julianadormon commented 3 weeks ago

I am facing the same issue as well I am running .net 9 and this has been happening since .net 6. I ended up not using Maui for this very reason before. This is a huge problem as it makes using Maui useless if you want to develop software for the mac.

Sometimes it can be hours before I see this and then all of a sudden the app may refresh itself 2 or 3 times in a matter of minutes. This makes me wonder if memory is somehow related. But I usually notice then happen when I am not using the app. It quite literally refreshes the webview for no apparent reason.

julianadormon commented 3 weeks ago

I was able to capture a video of the problem.

https://www.loom.com/share/d9f4146234184d9b996948ecd7b1e2f8?sid=01d2c0b6-1195-4f61-9cf8-bf6c6cf7fa07

This video shows the Maui Blazor app reloading itself. The app is the middle window with the 4 images of the basket ball player being photographed. The one with the purple triangle in the bottom right of its window. Behind that the app is highlighted in the Activity monitor. The memory usage fluctuates slightly but stays within a range of 385 - 390 MBs. The threads stays constant with 17. I see no memory leaks. The app is not the focused window. You will see that I switch to Rider to do some work and when I return to the original desktop, the Maui app is in mid load and it screen is refreshing. When it reloads we see the same content. This is only because my app uses a local SQLite database to save state. The strange thing is that the app reloads the current route, so it's almost like NavigationManager is reloading the current "page" component. There is nothing in the Safari debug console relating to a reload.

My application is part of a much larger solution that I cannot share but the Maui app is brand new .net 9 project using the new Blazor server/Maui project with a shared component library. Sory I do not remember the exact name of template. As I mentioned in my previous comment above, I have seen this behavior in other Maui apps I have built since .net 6.

I have no idea how to log this behavior, so if you can give me any suggestions, I can try to implement this to help you understand the issue better.

julianadormon commented 3 weeks ago

@drasticactions You mentioned that you tested this overnight and was still available the next day, but as you can see in my video above that unless you see it happen, it could very well be restored the to the current view it was on before refreshing. In other words it doesn't mean it didn't happen. Thanks.

julianadormon commented 3 weeks ago

I just caught it doing it again and when it reloads, I can confirm that the content of the window shows the Loading... message when the app initializes. Then returns to the last route it was on.

julianadormon commented 3 weeks ago

Sorry to beat a dead horse, but I had a logger attached and it seems that this occurs on 30 minute schedule: Here is a video: https://www.loom.com/share/5b950d8cc292498baaf64c71b64331d3?sid=1aa7c4fb-7feb-409c-a046-756a3a5efb4b