maui icon indicating copy to clipboard operation
maui copied to clipboard

Add support for hosted services in .NET MAUI apps

Open Eilon opened this issue 4 years ago • 23 comments

Look into using hosted services. This would replace the icky IMauiInitializeService that was added in https://github.com/dotnet/maui/pull/2137, and also to enable users to use hosted services. MAUI will automatically call StartAsync/StopAsync at the appropriate time. Sadly, this pattern is async-only, whereas in MAUI the call sites are always (or at least almost always) sync. But given that this is app startup/shutdown, doing async-over-sync might be OK (we would block).

This is a follow-up to PR https://github.com/dotnet/maui/pull/2137.

Other notes:

  • Need to consider this when implementing: https://github.com/dotnet/aspnetcore/pull/36122

Eilon avatar Aug 25 '21 05:08 Eilon

But given that this is app startup/shutdown, doing async-over-sync might be OK (we would block).

I think this is reasonable. That's effectively what happens when a Program.Main() uses the generic host. Even with an async Program.Main(), the compiler synthesizes the real entry point which blocks.

halter73 avatar Aug 25 '21 21:08 halter73

Just to clarify my understanding, this would mean once supported i could drop the following icky code I'm using? I pass the IHostEnvironment environment to some wiring code, The maui App assembly is just "HeroesProfile", but i use shared IoC registration. To give some context on how I'm using DI.

 /*
             * Hosted services only works with the Hosting Extensions from .NET
             * Maui does not use the same Hosting service and so we much register them differently depending on how we execute background services.
             * If this is for Maui, we must hook into Application startup and run the services.
             * If this is for Console, .AddHostedService will handle starting the services for us.
             */
            if (environment.ApplicationName.Equals("HeroesProfile.Console"))
            {
                services
                    .AddHostedService<GameSimulator>()
                    .AddHostedService<FileWatchers>()
                    .AddHostedService<OnLaunchReplayProcessor>();
            }
            else
            {
                services
                    .AddSingleton<GameSimulator>()
                    .AddSingleton<FileWatchers>()
                    .AddSingleton<OnLaunchReplayProcessor>();
            }

pjmagee avatar Sep 30 '21 16:09 pjmagee

@pjmagee yeah I think so. If we implement this, there would be proper support for hosted services so all the regular APIs that exist for that would work as expected (starting/stopping those services).

Eilon avatar Sep 30 '21 16:09 Eilon

Dumb question hopefully not too off-topic; what does an IHostedService mean on Android? Will that behave like an Android foreground service or will it only live as long as the MAUI app is running? I want to run an always-on .NET 5 BackgroundService on my Android smartphone and am a little lost figuring out how to utilize MAUI or net6.0-android for that yet.

RayKoopa avatar Nov 03 '21 19:11 RayKoopa

@RayKoopa - This would be for in-app in-proc services. So they would start when the app starts, and dies when the app dies. I'm not sure in Android terminology what that equates to, but it's not a background thing.

Eilon avatar Nov 03 '21 19:11 Eilon

@Eilon Ah alright, I expected it to be "app-wide". I'll try to figure out how to host my Android foreground service then (which is like a "system-wide" background thread with a notification, that has no connection to an app or UI once started). Thanks for the fast reply!

RayKoopa avatar Nov 03 '21 20:11 RayKoopa

Any news from this issue?

hflexgrig avatar Dec 08 '21 22:12 hflexgrig

@Eilon Added pull request for this issue https://github.com/dotnet/maui/pull/3718

hflexgrig avatar Dec 09 '21 22:12 hflexgrig

@hflexgrig oh wow I'll take a look!

Eilon avatar Dec 09 '21 23:12 Eilon

@Eilon deleted old one and create new https://github.com/dotnet/maui/pull/3724

hflexgrig avatar Dec 10 '21 03:12 hflexgrig

any status on this feature? Thanks

obenyaala avatar Nov 28 '22 08:11 obenyaala

will there ever be hosted services?

ctigrisht avatar Jan 05 '23 12:01 ctigrisht

FWIW, having native IHostedService support would allow OpenIddict users to use the new OpenIddict.Client.SystemIntegration package on MAUI/WinUI. I posted more information here: https://github.com/openiddict/openiddict-core/pull/1480#issuecomment-1397746558.

kevinchalet avatar Jan 19 '23 23:01 kevinchalet

This kind of addition would definitely make it easier to work with an abstracted service model instead of platform specific service implementations.

JohnHunterACS avatar Jan 26 '23 11:01 JohnHunterACS

Any news about this? Currently stuck because of this...

DoubleDBE avatar Mar 15 '23 10:03 DoubleDBE

This work is not currently planned. Could you manually start the services in MauiProgram or another part of the app? Certainly not ideal, but it could be a reasonable workaround.

Eilon avatar Mar 15 '23 16:03 Eilon

This work is not currently planned. Could you manually start the services in MauiProgram or another part of the app? Certainly not ideal, but it could be a reasonable workaround.

Does this really work in Android when screen is switched off?

janseris avatar Mar 11 '24 22:03 janseris

Any updates?

bdovaz avatar Sep 16 '24 06:09 bdovaz

Need this

symbiogenesis avatar Oct 04 '24 05:10 symbiogenesis

I'm also looking forward to seeing it in MAUI. In the meantime, what is the best practice for MAUI to have background tasks that periodically perform REST requests to get data?

mariuszdybala avatar Oct 17 '24 09:10 mariuszdybala

I'm also looking forward to seeing it in MAUI. In the meantime, what is the best practice for MAUI to have background tasks that periodically perform REST requests to get data?

I think you can take the concept of a hosted service but you need to activate those in the Maui Startup event. that's basically the best workaround we have, not sure the impact on different devices though.

pjmagee avatar Oct 17 '24 10:10 pjmagee

Hosted services will run while the app is active in the foreground only, right?

Haukinger avatar Oct 17 '24 10:10 Haukinger

I'm also looking forward to seeing it in MAUI. In the meantime, what is the best practice for MAUI to have background tasks that periodically perform REST requests to get data?

I use a singleton service that initializes a dispatcher timer on a certain interval, which is wired up in the constructor of the service.

A hosted service would be better, for a number of reasons. But that is adequate-ish.

i.e.

.AddSingleton<ISyncService, SyncService>()

and

internal sealed class SyncService : ISyncService, IDisposable
{
    private readonly IDispatcherTimer syncTimer;

    public SyncService()
    {
        // Set a timer to execute the sync on an interval
        this.syncTimer = Application.Current.Dispatcher.CreateTimer();
        this.syncTimer.Interval = TimeSpan.FromMinutes(2);
        this.syncTimer.Tick += this.OnSyncTimerElapsed;
    }

    private void OnSyncTimerElapsed(object? sender, EventArgs e)
    {
        // Do Stuff Here
    }
}

symbiogenesis avatar Oct 17 '24 23:10 symbiogenesis

Any update?

illuminat3 avatar Oct 31 '24 16:10 illuminat3

Any update?

MacKey-255 avatar Apr 01 '25 20:04 MacKey-255

You can grab this file and register it as HostedService:

builder.Services.AddSingleton<HostedServiceExecutor>(); Then just before returning app, you can call it

using (var scope = app.Services.CreateScope())
{
    var hsExecutor = scope.ServiceProvider.GetRequiredService<HostedServiceExecutor>();
        hsExecutor.StartAsync(default).GetAwaiter().GetResult();
}
return app;

After that it start all your Hosted/Background services.

jakubmaguza avatar Jul 04 '25 18:07 jakubmaguza